@apollo/gateway 2.3.4 → 2.4.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,101 @@
1
+ import gql from 'graphql-tag';
2
+ import { startSubgraphsAndGateway, Services } from './testUtils'
3
+
4
+ let services: Services;
5
+
6
+ afterEach(async () => {
7
+ if (services) {
8
+ await services.stop();
9
+ }
10
+ });
11
+
12
+ describe('`debug.bypassPlannerForSingleSubgraph` config', () => {
13
+ const subgraph = {
14
+ name: 'A',
15
+ url: 'https://A',
16
+ typeDefs: gql`
17
+ type Query {
18
+ a: A
19
+ }
20
+
21
+ type A {
22
+ b: B
23
+ }
24
+
25
+ type B {
26
+ x: Int
27
+ y: String
28
+ }
29
+ `,
30
+ resolvers: {
31
+ Query: {
32
+ a: () => ({
33
+ b: {
34
+ x: 1,
35
+ y: 'foo',
36
+ }
37
+ }),
38
+ }
39
+ }
40
+ };
41
+
42
+ const query = `
43
+ {
44
+ a {
45
+ b {
46
+ x
47
+ y
48
+ }
49
+ }
50
+ }
51
+ `;
52
+
53
+ const expectedResult = `
54
+ Object {
55
+ "data": Object {
56
+ "a": Object {
57
+ "b": Object {
58
+ "x": 1,
59
+ "y": "foo",
60
+ },
61
+ },
62
+ },
63
+ }
64
+ `;
65
+
66
+ it('is disabled by default', async () => {
67
+ services = await startSubgraphsAndGateway([subgraph]);
68
+
69
+ const response = await services.queryGateway(query);
70
+ const result = await response.json();
71
+ expect(result).toMatchInlineSnapshot(expectedResult);
72
+
73
+ const queryPlanner = services.gateway.__testing().queryPlanner!;
74
+ // If the query planner is genuinely used, we shoud have evaluated 1 plan.
75
+ expect(queryPlanner.lastGeneratedPlanStatistics()?.evaluatedPlanCount).toBe(1);
76
+ });
77
+
78
+ it('works when enabled', async () => {
79
+ services = await startSubgraphsAndGateway(
80
+ [subgraph],
81
+ {
82
+ gatewayConfig: {
83
+ queryPlannerConfig: {
84
+ debug: {
85
+ bypassPlannerForSingleSubgraph: true,
86
+ }
87
+ }
88
+ }
89
+ }
90
+ );
91
+
92
+ const response = await services.queryGateway(query);
93
+ const result = await response.json();
94
+ expect(result).toMatchInlineSnapshot(expectedResult);
95
+
96
+ const queryPlanner = services.gateway.__testing().queryPlanner!;
97
+ // The `bypassPlannerForSingleSubgraph` doesn't evaluate anything. It's use is the only case where `evaluatedPlanCount` can be 0.
98
+ expect(queryPlanner.lastGeneratedPlanStatistics()?.evaluatedPlanCount).toBe(0);
99
+ });
100
+ });
101
+
@@ -1,20 +1,17 @@
1
1
  import { gunzipSync } from 'zlib';
2
2
  import nock from 'nock';
3
3
  import gql from 'graphql-tag';
4
- import { buildSubgraphSchema } from '@apollo/subgraph';
5
- import { ApolloServer } from 'apollo-server';
6
- import { ApolloServerPluginUsageReporting } from 'apollo-server-core';
4
+ import { ApolloServerPluginUsageReporting } from '@apollo/server/plugin/usageReporting';
7
5
  import { execute } from '@apollo/client/link/core';
8
6
  import { toPromise } from '@apollo/client/link/utils';
9
7
  import { createHttpLink } from '@apollo/client/link/http';
10
8
  import fetch from 'node-fetch';
11
- import { ApolloGateway } from '../..';
12
9
  import { Plugin, Config, Refs } from 'pretty-format';
13
10
  import { Report, Trace } from '@apollo/usage-reporting-protobuf';
14
11
  import { fixtures } from 'apollo-federation-integration-testsuite';
15
12
  import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
16
- import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper';
17
13
  import resolvable, { Resolvable } from '@josephg/resolvable';
14
+ import { startSubgraphsAndGateway, Services } from './testUtils';
18
15
 
19
16
  // Normalize specific fields that change often (eg timestamps) to static values,
20
17
  // to make snapshot testing viable. (If these helpers are more generally
@@ -80,17 +77,8 @@ expect.addSnapshotSerializer(
80
77
  }),
81
78
  );
82
79
 
83
- async function startFederatedServer(modules: GraphQLSchemaModule[]) {
84
- const schema = buildSubgraphSchema(modules);
85
- const server = new ApolloServer({ schema });
86
- const { url } = await server.listen({ port: 0 });
87
- return { url, server };
88
- }
89
-
90
80
  describe('reporting', () => {
91
- let backendServers: ApolloServer[];
92
- let gatewayServer: ApolloServer;
93
- let gatewayUrl: string;
81
+ let services: Services;
94
82
  let reportPromise: Resolvable<any>;
95
83
 
96
84
  beforeEach(async () => {
@@ -104,38 +92,27 @@ describe('reporting', () => {
104
92
  return 'ok';
105
93
  });
106
94
 
107
- backendServers = [];
108
- const serviceList = [];
109
- for (const fixture of fixtures) {
110
- const { server, url } = await startFederatedServer([fixture]);
111
- backendServers.push(server);
112
- serviceList.push({ name: fixture.name, url });
113
- }
114
-
115
- const gateway = new ApolloGateway({ serviceList });
116
- const { schema, executor } = await gateway.load();
117
- gatewayServer = new ApolloServer({
118
- schema,
119
- executor,
120
- apollo: {
121
- key: 'service:foo:bar',
122
- graphRef: 'foo@current',
123
- },
124
- plugins: [
125
- ApolloServerPluginUsageReporting({
126
- sendReportsImmediately: true,
127
- }),
128
- ],
129
- });
130
- ({ url: gatewayUrl } = await gatewayServer.listen({ port: 0 }));
95
+ services = await startSubgraphsAndGateway(
96
+ fixtures,
97
+ {
98
+ gatewayServerConfig: {
99
+ apollo: {
100
+ key: 'service:foo:bar',
101
+ graphRef: 'foo@current',
102
+ },
103
+ plugins: [
104
+ ApolloServerPluginUsageReporting({
105
+ sendReportsImmediately: true,
106
+ }),
107
+ ],
108
+ },
109
+ }
110
+ );
131
111
  });
132
112
 
133
113
  afterEach(async () => {
134
- for (const server of backendServers) {
135
- await server.stop();
136
- }
137
- if (gatewayServer) {
138
- await gatewayServer.stop();
114
+ if (services) {
115
+ await services.stop();
139
116
  }
140
117
 
141
118
  nockAfterEach();
@@ -157,7 +134,7 @@ describe('reporting', () => {
157
134
  `;
158
135
 
159
136
  const result = await toPromise(
160
- execute(createHttpLink({ uri: gatewayUrl, fetch: fetch as any }), {
137
+ execute(createHttpLink({ uri: services.gatewayUrl, fetch: fetch as any }), {
161
138
  query,
162
139
  }),
163
140
  );
@@ -632,6 +609,7 @@ describe('reporting', () => {
632
609
  ],
633
610
  },
634
611
  },
612
+ "tracesPreAggregated": false,
635
613
  }
636
614
  `);
637
615
  });
@@ -6,13 +6,15 @@ import {
6
6
  } from '@apollo/gateway';
7
7
  import { accounts, fixturesWithUpdate } from 'apollo-federation-integration-testsuite';
8
8
  import { createHash } from '@apollo/utils.createhash';
9
- import { ApolloServer } from 'apollo-server';
9
+ import { ApolloServer } from '@apollo/server';
10
+ import { startStandaloneServer } from '@apollo/server/standalone';
10
11
  import type { Logger } from '@apollo/utils.logger';
11
12
  import { getTestingSupergraphSdl } from '../execution-utils';
12
13
  import { mockAllServicesHealthCheckSuccess } from '../integration/nockMocks';
13
14
  import resolvable from '@josephg/resolvable';
14
15
  import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
15
16
  import nock from 'nock';
17
+ import { unwrapSingleResultKind } from '../gateway/testUtils';
16
18
 
17
19
  async function getSupergraphSdlGatewayServer() {
18
20
  const server = new ApolloServer({
@@ -26,7 +28,7 @@ async function getSupergraphSdlGatewayServer() {
26
28
  }),
27
29
  });
28
30
 
29
- await server.listen({ port: 0 });
31
+ await startStandaloneServer(server, { listen: { port: 0 } });
30
32
  return server;
31
33
  }
32
34
 
@@ -67,7 +69,7 @@ describe('Using supergraphSdl static configuration', () => {
67
69
  query: '{ me { username } }',
68
70
  });
69
71
 
70
- expect(result.data).toMatchInlineSnapshot(`
72
+ expect(unwrapSingleResultKind(result).data).toMatchInlineSnapshot(`
71
73
  Object {
72
74
  "me": Object {
73
75
  "username": "@jbaxleyiii",
@@ -0,0 +1,89 @@
1
+ import { buildSubgraphSchema } from '@apollo/subgraph';
2
+ import {
3
+ ApolloServer,
4
+ ApolloServerOptionsWithGateway,
5
+ BaseContext,
6
+ GraphQLResponse,
7
+ } from '@apollo/server';
8
+ import { startStandaloneServer } from '@apollo/server/standalone';
9
+ import { ApolloServerPluginInlineTrace } from '@apollo/server/plugin/inlineTrace';
10
+ import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper';
11
+ import { ApolloGateway, GatewayConfig } from '../..';
12
+ import { ServiceDefinition } from '@apollo/federation-internals';
13
+ import fetch, { Response } from 'node-fetch';
14
+ import { assert } from '@apollo/federation-internals';
15
+
16
+ export class Services {
17
+ constructor(
18
+ readonly subgraphServers: ApolloServer[],
19
+ readonly gateway: ApolloGateway,
20
+ readonly gatewayServer: ApolloServer,
21
+ readonly gatewayUrl: string,
22
+ ) {
23
+ }
24
+
25
+ async queryGateway(query: string): Promise<Response> {
26
+ return fetch(this.gatewayUrl, {
27
+ method: 'POST',
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ },
31
+ body: JSON.stringify({ query }),
32
+ });
33
+ }
34
+
35
+ async stop() {
36
+ for (const server of this.subgraphServers) {
37
+ await server.stop();
38
+ }
39
+ await this.gatewayServer.stop();
40
+ }
41
+ }
42
+
43
+ async function startFederatedServer(modules: GraphQLSchemaModule[]) {
44
+ const schema = buildSubgraphSchema(modules);
45
+ const server = new ApolloServer({
46
+ schema,
47
+ // Manually installing the inline trace plugin means it doesn't log a message.
48
+ plugins: [ApolloServerPluginInlineTrace()],
49
+ });
50
+ const { url } = await startStandaloneServer(server, { listen: { port: 0 } });
51
+ return { url, server };
52
+ }
53
+
54
+ export async function startSubgraphsAndGateway(
55
+ servicesDefs: ServiceDefinition[],
56
+ config?: {
57
+ gatewayConfig?: GatewayConfig;
58
+ gatewayServerConfig?: Partial<ApolloServerOptionsWithGateway<BaseContext>>;
59
+ },
60
+ ): Promise<Services> {
61
+ const backendServers = [];
62
+ const serviceList = [];
63
+ for (const serviceDef of servicesDefs) {
64
+ const { server, url } = await startFederatedServer([serviceDef]);
65
+ backendServers.push(server);
66
+ serviceList.push({ name: serviceDef.name, url });
67
+ }
68
+
69
+ const gateway = new ApolloGateway({
70
+ serviceList,
71
+ ...config?.gatewayConfig,
72
+ });
73
+ const gatewayServer = new ApolloServer({
74
+ gateway,
75
+ ...config?.gatewayServerConfig,
76
+ });
77
+ const { url: gatewayUrl } = await startStandaloneServer(gatewayServer, {
78
+ listen: { port: 0 },
79
+ });
80
+ return new Services(backendServers, gateway, gatewayServer, gatewayUrl);
81
+ }
82
+
83
+ export function unwrapSingleResultKind(response: GraphQLResponse) {
84
+ assert(
85
+ response.body.kind === 'single',
86
+ `Expected single result, got ${response.body.kind}`,
87
+ );
88
+ return response.body.singleResult;
89
+ }
@@ -1,9 +1,10 @@
1
1
  import { execute } from '../execution-utils';
2
- import { ApolloServerBase as ApolloServer } from 'apollo-server-core';
2
+ import { ApolloServer } from '@apollo/server';
3
3
  import { buildSubgraphSchema } from '@apollo/subgraph';
4
4
  import { LocalGraphQLDataSource } from '../../datasources/LocalGraphQLDataSource';
5
5
  import { ApolloGateway } from '../../';
6
6
  import { fixtures } from 'apollo-federation-integration-testsuite';
7
+ import { unwrapSingleResultKind } from '../gateway/testUtils';
7
8
 
8
9
  it('supports simple aliases', async () => {
9
10
  const query = `#graphql
@@ -155,9 +156,8 @@ it('supports aliases when using ApolloServer', async () => {
155
156
  },
156
157
  });
157
158
 
158
- const { schema, executor } = await gateway.load();
159
-
160
- const server = new ApolloServer({ schema, executor });
159
+ const server = new ApolloServer({ gateway });
160
+ await server.start();
161
161
 
162
162
  const upc = '1';
163
163
 
@@ -172,7 +172,7 @@ it('supports aliases when using ApolloServer', async () => {
172
172
  variables: { upc },
173
173
  });
174
174
 
175
- expect(result.data).toEqual({
175
+ expect(unwrapSingleResultKind(result).data).toEqual({
176
176
  product: {
177
177
  title: 'Table',
178
178
  },
@@ -4,8 +4,6 @@ import { astSerializer, queryPlanSerializer } from 'apollo-federation-integratio
4
4
  expect.addSnapshotSerializer(astSerializer);
5
5
  expect.addSnapshotSerializer(queryPlanSerializer);
6
6
 
7
- // TODO: right now the query planner doesn't prune known skip and include points
8
- // eventually we want to do this to prevent downstream fetches that aren't needed
9
7
  describe('@skip', () => {
10
8
  it('supports @skip when a boolean condition is met', async () => {
11
9
  const query = `#graphql
@@ -35,8 +33,8 @@ describe('@skip', () => {
35
33
  ],
36
34
  });
37
35
 
38
- expect(queryPlan).toCallService('accounts');
39
36
  expect(queryPlan).toCallService('reviews');
37
+ expect(queryPlan).not.toCallService('accounts');
40
38
  });
41
39
 
42
40
  it('supports @skip when a boolean condition is met (variable driven)', async () => {
@@ -122,7 +120,7 @@ describe('@skip', () => {
122
120
  `;
123
121
 
124
122
  const skip = false;
125
- const { data, queryPlan } = await execute({
123
+ const { data, queryPlan, operation } = await execute({
126
124
  query,
127
125
  variables: { skip },
128
126
  });
@@ -137,8 +135,9 @@ describe('@skip', () => {
137
135
  ],
138
136
  });
139
137
 
140
- expect(queryPlan).toCallService('accounts');
141
- expect(queryPlan).toCallService('reviews');
138
+ const variables = { definitions: operation.variableDefinitions, values: {skip} };
139
+ expect(queryPlan).toCallService('reviews', variables);
140
+ expect(queryPlan).toCallService('accounts', variables);
142
141
  });
143
142
  });
144
143
 
@@ -258,7 +257,7 @@ describe('@include', () => {
258
257
  `;
259
258
 
260
259
  const include = true;
261
- const { data, queryPlan } = await execute({
260
+ const { data, queryPlan, operation } = await execute({
262
261
  query,
263
262
  variables: { include },
264
263
  });
@@ -273,7 +272,8 @@ describe('@include', () => {
273
272
  ],
274
273
  });
275
274
 
276
- expect(queryPlan).toCallService('accounts');
277
- expect(queryPlan).toCallService('reviews');
275
+ const variables = { definitions: operation.variableDefinitions, values: {include} };
276
+ expect(queryPlan).toCallService('accounts', variables);
277
+ expect(queryPlan).toCallService('reviews', variables);
278
278
  });
279
279
  });
@@ -2,8 +2,9 @@ import mockedEnv from 'mocked-env';
2
2
  import fetcher from 'make-fetch-happen';
3
3
 
4
4
  import { ApolloGateway, UplinkSupergraphManager } from '@apollo/gateway';
5
- import { ApolloServer } from 'apollo-server';
6
- import { ApolloServerPluginUsageReportingDisabled } from 'apollo-server-core';
5
+ import { ApolloServer } from '@apollo/server';
6
+ import { startStandaloneServer } from '@apollo/server/standalone';
7
+ import { ApolloServerPluginUsageReportingDisabled } from '@apollo/server/plugin/disabled';
7
8
  import type { FetcherRequestInit } from '@apollo/utils.fetcher';
8
9
 
9
10
  import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
@@ -62,7 +63,7 @@ describe('minimal gateway', () => {
62
63
  gateway,
63
64
  plugins: [ApolloServerPluginUsageReportingDisabled()],
64
65
  });
65
- await server.listen({ port: 0 });
66
+ await startStandaloneServer(server, { listen: { port: 0 } });
66
67
  expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
67
68
  });
68
69
 
@@ -80,7 +81,7 @@ describe('minimal gateway', () => {
80
81
  gateway,
81
82
  plugins: [ApolloServerPluginUsageReportingDisabled()],
82
83
  });
83
- await server.listen({ port: 0 });
84
+ await startStandaloneServer(server, { listen: { port: 0 } });
84
85
  expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
85
86
  const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
86
87
  expect(uplinkManager.uplinkEndpoints).toEqual([uplinkEndpoint]);
@@ -100,7 +101,7 @@ describe('minimal gateway', () => {
100
101
  gateway,
101
102
  plugins: [ApolloServerPluginUsageReportingDisabled()],
102
103
  });
103
- await server.listen({ port: 0 });
104
+ await startStandaloneServer(server, { listen: { port: 0 } });
104
105
  expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
105
106
  const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
106
107
  expect(uplinkManager.uplinkEndpoints).toEqual([
@@ -127,7 +128,7 @@ describe('minimal gateway', () => {
127
128
  gateway,
128
129
  plugins: [ApolloServerPluginUsageReportingDisabled()],
129
130
  });
130
- await server.listen({ port: 0 });
131
+ await startStandaloneServer(server, { listen: { port: 0 } });
131
132
 
132
133
  expect(calls).toEqual(1);
133
134
  });
@@ -180,7 +181,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
180
181
 
181
182
  const supergraphSchema = getTestingSupergraphSdl();
182
183
  let hasFired;
183
- let uplinkManager = new UplinkSupergraphManager({
184
+ const uplinkManager = new UplinkSupergraphManager({
184
185
  apiKey,
185
186
  graphRef,
186
187
  logger,
@@ -246,7 +247,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
246
247
  .reply(500);
247
248
 
248
249
  let hasFired;
249
- let uplinkManager = new UplinkSupergraphManager({
250
+ const uplinkManager = new UplinkSupergraphManager({
250
251
  apiKey,
251
252
  graphRef,
252
253
  logger,
@@ -285,7 +286,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
285
286
  .reply(500);
286
287
 
287
288
  let hasFired;
288
- let uplinkManager = new UplinkSupergraphManager({
289
+ const uplinkManager = new UplinkSupergraphManager({
289
290
  apiKey,
290
291
  graphRef,
291
292
  logger,
@@ -28,12 +28,13 @@ import {
28
28
  getResponseName,
29
29
  FetchDataInputRewrite,
30
30
  FetchDataOutputRewrite,
31
+ evaluateCondition,
31
32
  } from '@apollo/query-planner';
32
33
  import { deepMerge } from './utilities/deepMerge';
33
34
  import { isNotNullOrUndefined } from './utilities/array';
34
35
  import { SpanStatusCode } from "@opentelemetry/api";
35
36
  import { OpenTelemetrySpanNames, tracer } from "./utilities/opentelemetry";
36
- import { assert, defaultRootName, errorCodeDef, ERRORS, isDefined, operationFromDocument, Schema } from '@apollo/federation-internals';
37
+ import { assert, defaultRootName, errorCodeDef, ERRORS, isDefined, Operation, operationFromDocument, Schema } from '@apollo/federation-internals';
37
38
  import { GatewayGraphQLRequestContext, GatewayExecutionResult } from '@apollo/server-gateway-interface';
38
39
  import { computeResponse } from './resultShaping';
39
40
 
@@ -64,6 +65,7 @@ type ResultCursor = {
64
65
  interface ExecutionContext {
65
66
  queryPlan: QueryPlan;
66
67
  operationContext: OperationContext;
68
+ operation: Operation,
67
69
  serviceMap: ServiceMap;
68
70
  requestContext: GatewayGraphQLRequestContext;
69
71
  supergraphSchema: GraphQLSchema;
@@ -114,9 +116,39 @@ export async function executeQueryPlan(
114
116
  try {
115
117
  const errors: GraphQLError[] = [];
116
118
 
119
+ let operation: Operation;
120
+ try {
121
+ operation = operationFromDocument(
122
+ apiSchema,
123
+ {
124
+ kind: Kind.DOCUMENT,
125
+ definitions: [
126
+ operationContext.operation,
127
+ ...Object.values(operationContext.fragments),
128
+ ],
129
+ },
130
+ {
131
+ validate: false,
132
+ }
133
+ );
134
+ } catch (err) {
135
+ // We shouldn't really have errors as the operation should already have been validated, but if something still
136
+ // happens, we should report it properly (plus, some of our tests call this method directly and blow up if we don't
137
+ // handle this correctly).
138
+ // TODO: we are doing some duplicate work by building both `OperationContext` and this `Operation`. Ideally we
139
+ // would remove `OperationContext`, pass the `Operation` directly to this method, and only use that. This would change
140
+ // the signature of this method though and it is exported so ... maybe later ?
141
+ //
142
+ if (err instanceof GraphQLError) {
143
+ return { errors: [err] };
144
+ }
145
+ throw err;
146
+ }
147
+
117
148
  const context: ExecutionContext = {
118
149
  queryPlan,
119
150
  operationContext,
151
+ operation,
120
152
  serviceMap,
121
153
  requestContext,
122
154
  supergraphSchema,
@@ -129,6 +161,10 @@ export async function executeQueryPlan(
129
161
  requestContext.metrics && requestContext.metrics.captureTraces
130
162
  );
131
163
 
164
+ if (queryPlan.node?.kind === 'Subscription') {
165
+ throw new Error('Execution of subscriptions not supported by gateway');
166
+ }
167
+
132
168
  if (queryPlan.node) {
133
169
  const traceNode = await executeNode(
134
170
  context,
@@ -148,20 +184,6 @@ export async function executeQueryPlan(
148
184
  const result = await tracer.startActiveSpan(OpenTelemetrySpanNames.POST_PROCESSING, async (span) => {
149
185
  let data;
150
186
  try {
151
- const operation = operationFromDocument(
152
- apiSchema,
153
- {
154
- kind: Kind.DOCUMENT,
155
- definitions: [
156
- operationContext.operation,
157
- ...Object.values(operationContext.fragments),
158
- ],
159
- },
160
- {
161
- validate: false,
162
- }
163
- );
164
-
165
187
  let postProcessingErrors: GraphQLError[];
166
188
  ({ data, errors: postProcessingErrors } = computeResponse({
167
189
  operation,
@@ -326,12 +348,30 @@ async function executeNode(
326
348
  }
327
349
  return new Trace.QueryPlanNode({ fetch: traceNode });
328
350
  }
351
+ case 'Condition': {
352
+ const condition = evaluateCondition(node, context.operation.variableDefinitions, context.requestContext.request.variables);
353
+ const pickedBranch = condition ? node.ifClause : node.elseClause;
354
+ let branchTraceNode: Trace.QueryPlanNode | undefined = undefined;
355
+ if (pickedBranch) {
356
+ branchTraceNode = await executeNode(
357
+ context,
358
+ pickedBranch,
359
+ currentCursor,
360
+ captureTraces
361
+ );
362
+ }
363
+
364
+ return new Trace.QueryPlanNode({
365
+ condition: new Trace.QueryPlanNode.ConditionNode({
366
+ condition: node.condition,
367
+ ifClause: condition ? branchTraceNode : undefined,
368
+ elseClause: condition ? undefined : branchTraceNode,
369
+ }),
370
+ });
371
+ }
329
372
  case 'Defer': {
330
373
  assert(false, `@defer support is not available in the gateway`);
331
374
  }
332
- case 'Condition': {
333
- assert(false, `Condition nodes are not available in the gateway`);
334
- }
335
375
  }
336
376
  }
337
377