@apollo/gateway 0.300.0-alpha.3 → 2.0.0-alpha.3

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.
Files changed (199) hide show
  1. package/LICENSE +95 -0
  2. package/README.md +1 -1
  3. package/dist/__generated__/graphqlTypes.d.ts +130 -0
  4. package/dist/__generated__/graphqlTypes.d.ts.map +1 -0
  5. package/dist/__generated__/graphqlTypes.js +25 -0
  6. package/dist/__generated__/graphqlTypes.js.map +1 -0
  7. package/dist/config.d.ts +106 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +47 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/datasources/LocalGraphQLDataSource.d.ts +3 -3
  12. package/dist/datasources/LocalGraphQLDataSource.d.ts.map +1 -1
  13. package/dist/datasources/LocalGraphQLDataSource.js +5 -5
  14. package/dist/datasources/LocalGraphQLDataSource.js.map +1 -1
  15. package/dist/datasources/RemoteGraphQLDataSource.d.ts +6 -4
  16. package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
  17. package/dist/datasources/RemoteGraphQLDataSource.js +64 -18
  18. package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
  19. package/dist/datasources/index.d.ts +1 -1
  20. package/dist/datasources/index.d.ts.map +1 -1
  21. package/dist/datasources/index.js +1 -0
  22. package/dist/datasources/index.js.map +1 -1
  23. package/dist/datasources/parseCacheControlHeader.d.ts +2 -0
  24. package/dist/datasources/parseCacheControlHeader.d.ts.map +1 -0
  25. package/dist/datasources/parseCacheControlHeader.js +16 -0
  26. package/dist/datasources/parseCacheControlHeader.js.map +1 -0
  27. package/dist/datasources/types.d.ts +16 -1
  28. package/dist/datasources/types.d.ts.map +1 -1
  29. package/dist/datasources/types.js +7 -0
  30. package/dist/datasources/types.js.map +1 -1
  31. package/dist/executeQueryPlan.d.ts +2 -1
  32. package/dist/executeQueryPlan.d.ts.map +1 -1
  33. package/dist/executeQueryPlan.js +200 -113
  34. package/dist/executeQueryPlan.js.map +1 -1
  35. package/dist/index.d.ts +64 -80
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +554 -233
  38. package/dist/index.js.map +1 -1
  39. package/dist/loadServicesFromRemoteEndpoint.d.ts +9 -9
  40. package/dist/loadServicesFromRemoteEndpoint.d.ts.map +1 -1
  41. package/dist/loadServicesFromRemoteEndpoint.js +13 -8
  42. package/dist/loadServicesFromRemoteEndpoint.js.map +1 -1
  43. package/dist/loadSupergraphSdlFromStorage.d.ts +21 -0
  44. package/dist/loadSupergraphSdlFromStorage.d.ts.map +1 -0
  45. package/dist/loadSupergraphSdlFromStorage.js +128 -0
  46. package/dist/loadSupergraphSdlFromStorage.js.map +1 -0
  47. package/dist/operationContext.d.ts +17 -0
  48. package/dist/operationContext.d.ts.map +1 -0
  49. package/dist/operationContext.js +42 -0
  50. package/dist/operationContext.js.map +1 -0
  51. package/dist/outOfBandReporter.d.ts +13 -0
  52. package/dist/outOfBandReporter.d.ts.map +1 -0
  53. package/dist/outOfBandReporter.js +85 -0
  54. package/dist/outOfBandReporter.js.map +1 -0
  55. package/dist/utilities/array.d.ts +1 -2
  56. package/dist/utilities/array.d.ts.map +1 -1
  57. package/dist/utilities/array.js +7 -14
  58. package/dist/utilities/array.js.map +1 -1
  59. package/dist/utilities/assert.d.ts +2 -0
  60. package/dist/utilities/assert.d.ts.map +1 -0
  61. package/dist/utilities/assert.js +10 -0
  62. package/dist/utilities/assert.js.map +1 -0
  63. package/dist/utilities/cleanErrorOfInaccessibleNames.d.ts +3 -0
  64. package/dist/utilities/cleanErrorOfInaccessibleNames.d.ts.map +1 -0
  65. package/dist/utilities/cleanErrorOfInaccessibleNames.js +27 -0
  66. package/dist/utilities/cleanErrorOfInaccessibleNames.js.map +1 -0
  67. package/dist/utilities/deepMerge.js +2 -2
  68. package/dist/utilities/deepMerge.js.map +1 -1
  69. package/dist/utilities/graphql.d.ts +1 -4
  70. package/dist/utilities/graphql.d.ts.map +1 -1
  71. package/dist/utilities/graphql.js +3 -36
  72. package/dist/utilities/graphql.js.map +1 -1
  73. package/dist/utilities/opentelemetry.d.ts +10 -0
  74. package/dist/utilities/opentelemetry.d.ts.map +1 -0
  75. package/dist/utilities/opentelemetry.js +19 -0
  76. package/dist/utilities/opentelemetry.js.map +1 -0
  77. package/package.json +32 -23
  78. package/src/__generated__/graphqlTypes.ts +140 -0
  79. package/src/__mocks__/apollo-server-env.ts +56 -0
  80. package/src/__mocks__/make-fetch-happen-fetcher.ts +57 -0
  81. package/src/__mocks__/tsconfig.json +7 -0
  82. package/src/__tests__/build-query-plan.feature +40 -311
  83. package/src/__tests__/buildQueryPlan.test.ts +246 -426
  84. package/src/__tests__/executeQueryPlan.test.ts +2289 -194
  85. package/src/__tests__/execution-utils.ts +33 -26
  86. package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +195 -0
  87. package/src/__tests__/gateway/buildService.test.ts +16 -19
  88. package/src/__tests__/gateway/composedSdl.test.ts +44 -0
  89. package/src/__tests__/gateway/endToEnd.test.ts +166 -0
  90. package/src/__tests__/gateway/executor.test.ts +49 -43
  91. package/src/__tests__/gateway/lifecycle-hooks.test.ts +58 -29
  92. package/src/__tests__/gateway/opentelemetry.test.ts +123 -0
  93. package/src/__tests__/gateway/queryPlanCache.test.ts +19 -20
  94. package/src/__tests__/gateway/reporting.test.ts +83 -59
  95. package/src/__tests__/integration/abstract-types.test.ts +1086 -22
  96. package/src/__tests__/integration/aliases.test.ts +5 -6
  97. package/src/__tests__/integration/boolean.test.ts +40 -38
  98. package/src/__tests__/integration/complex-key.test.ts +41 -56
  99. package/src/__tests__/integration/configuration.test.ts +361 -0
  100. package/src/__tests__/integration/custom-directives.test.ts +61 -46
  101. package/src/__tests__/integration/fragments.test.ts +8 -2
  102. package/src/__tests__/integration/list-key.test.ts +2 -2
  103. package/src/__tests__/integration/logger.test.ts +2 -2
  104. package/src/__tests__/integration/multiple-key.test.ts +11 -12
  105. package/src/__tests__/integration/mutations.test.ts +8 -5
  106. package/src/__tests__/integration/networkRequests.test.ts +454 -294
  107. package/src/__tests__/integration/nockMocks.ts +100 -65
  108. package/src/__tests__/integration/provides.test.ts +9 -6
  109. package/src/__tests__/integration/requires.test.ts +17 -15
  110. package/src/__tests__/integration/scope.test.ts +557 -0
  111. package/src/__tests__/integration/unions.test.ts +1 -1
  112. package/src/__tests__/integration/value-types.test.ts +35 -32
  113. package/src/__tests__/integration/variables.test.ts +8 -2
  114. package/src/__tests__/loadServicesFromRemoteEndpoint.test.ts +6 -2
  115. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +343 -0
  116. package/src/__tests__/nockAssertions.ts +20 -0
  117. package/src/__tests__/queryPlanCucumber.test.ts +11 -61
  118. package/src/__tests__/testSetup.ts +1 -4
  119. package/src/__tests__/tsconfig.json +2 -1
  120. package/src/config.ts +227 -0
  121. package/src/core/__tests__/core.test.ts +412 -0
  122. package/src/datasources/LocalGraphQLDataSource.ts +9 -10
  123. package/src/datasources/RemoteGraphQLDataSource.ts +125 -45
  124. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +11 -4
  125. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +148 -79
  126. package/src/datasources/__tests__/tsconfig.json +4 -2
  127. package/src/datasources/index.ts +1 -1
  128. package/src/datasources/parseCacheControlHeader.ts +43 -0
  129. package/src/datasources/types.ts +47 -2
  130. package/src/executeQueryPlan.ts +275 -154
  131. package/src/index.ts +939 -480
  132. package/src/loadServicesFromRemoteEndpoint.ts +24 -17
  133. package/src/loadSupergraphSdlFromStorage.ts +186 -0
  134. package/src/make-fetch-happen.d.ts +2 -2
  135. package/src/operationContext.ts +70 -0
  136. package/src/outOfBandReporter.ts +126 -0
  137. package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +104 -0
  138. package/src/utilities/__tests__/tsconfig.json +8 -0
  139. package/src/utilities/array.ts +6 -28
  140. package/src/utilities/assert.ts +14 -0
  141. package/src/utilities/cleanErrorOfInaccessibleNames.ts +29 -0
  142. package/src/utilities/graphql.ts +0 -64
  143. package/src/utilities/opentelemetry.ts +13 -0
  144. package/CHANGELOG.md +0 -226
  145. package/LICENSE.md +0 -20
  146. package/dist/FieldSet.d.ts +0 -18
  147. package/dist/FieldSet.d.ts.map +0 -1
  148. package/dist/FieldSet.js +0 -96
  149. package/dist/FieldSet.js.map +0 -1
  150. package/dist/QueryPlan.d.ts +0 -41
  151. package/dist/QueryPlan.d.ts.map +0 -1
  152. package/dist/QueryPlan.js +0 -15
  153. package/dist/QueryPlan.js.map +0 -1
  154. package/dist/buildQueryPlan.d.ts +0 -44
  155. package/dist/buildQueryPlan.d.ts.map +0 -1
  156. package/dist/buildQueryPlan.js +0 -670
  157. package/dist/buildQueryPlan.js.map +0 -1
  158. package/dist/loadServicesFromStorage.d.ts +0 -21
  159. package/dist/loadServicesFromStorage.d.ts.map +0 -1
  160. package/dist/loadServicesFromStorage.js +0 -64
  161. package/dist/loadServicesFromStorage.js.map +0 -1
  162. package/dist/snapshotSerializers/astSerializer.d.ts +0 -3
  163. package/dist/snapshotSerializers/astSerializer.d.ts.map +0 -1
  164. package/dist/snapshotSerializers/astSerializer.js +0 -14
  165. package/dist/snapshotSerializers/astSerializer.js.map +0 -1
  166. package/dist/snapshotSerializers/index.d.ts +0 -13
  167. package/dist/snapshotSerializers/index.d.ts.map +0 -1
  168. package/dist/snapshotSerializers/index.js +0 -15
  169. package/dist/snapshotSerializers/index.js.map +0 -1
  170. package/dist/snapshotSerializers/queryPlanSerializer.d.ts +0 -3
  171. package/dist/snapshotSerializers/queryPlanSerializer.d.ts.map +0 -1
  172. package/dist/snapshotSerializers/queryPlanSerializer.js +0 -78
  173. package/dist/snapshotSerializers/queryPlanSerializer.js.map +0 -1
  174. package/dist/snapshotSerializers/selectionSetSerializer.d.ts +0 -3
  175. package/dist/snapshotSerializers/selectionSetSerializer.d.ts.map +0 -1
  176. package/dist/snapshotSerializers/selectionSetSerializer.js +0 -12
  177. package/dist/snapshotSerializers/selectionSetSerializer.js.map +0 -1
  178. package/dist/snapshotSerializers/typeSerializer.d.ts +0 -3
  179. package/dist/snapshotSerializers/typeSerializer.d.ts.map +0 -1
  180. package/dist/snapshotSerializers/typeSerializer.js +0 -12
  181. package/dist/snapshotSerializers/typeSerializer.js.map +0 -1
  182. package/dist/utilities/MultiMap.d.ts +0 -4
  183. package/dist/utilities/MultiMap.d.ts.map +0 -1
  184. package/dist/utilities/MultiMap.js +0 -17
  185. package/dist/utilities/MultiMap.js.map +0 -1
  186. package/src/FieldSet.ts +0 -169
  187. package/src/QueryPlan.ts +0 -57
  188. package/src/__tests__/matchers/toCallService.ts +0 -105
  189. package/src/__tests__/matchers/toHaveBeenCalledBefore.ts +0 -40
  190. package/src/__tests__/matchers/toHaveFetched.ts +0 -81
  191. package/src/__tests__/matchers/toMatchAST.ts +0 -64
  192. package/src/buildQueryPlan.ts +0 -1190
  193. package/src/loadServicesFromStorage.ts +0 -170
  194. package/src/snapshotSerializers/astSerializer.ts +0 -21
  195. package/src/snapshotSerializers/index.ts +0 -21
  196. package/src/snapshotSerializers/queryPlanSerializer.ts +0 -144
  197. package/src/snapshotSerializers/selectionSetSerializer.ts +0 -13
  198. package/src/snapshotSerializers/typeSerializer.ts +0 -11
  199. package/src/utilities/MultiMap.ts +0 -11
package/src/config.ts ADDED
@@ -0,0 +1,227 @@
1
+ import { GraphQLError, GraphQLSchema } from "graphql";
2
+ import { HeadersInit } from "node-fetch";
3
+ import { fetch } from 'apollo-server-env';
4
+ import { GraphQLRequestContextExecutionDidStart, Logger } from "apollo-server-types";
5
+ import { GraphQLDataSource } from './datasources/types';
6
+ import { QueryPlan } from '@apollo/query-planner';
7
+ import { OperationContext } from './operationContext';
8
+ import { ServiceMap } from './executeQueryPlan';
9
+ import { ServiceDefinition } from "@apollo/federation-internals";
10
+
11
+ export type ServiceEndpointDefinition = Pick<ServiceDefinition, 'name' | 'url'>;
12
+
13
+ export type Experimental_DidResolveQueryPlanCallback = ({
14
+ queryPlan,
15
+ serviceMap,
16
+ operationContext,
17
+ requestContext,
18
+ }: {
19
+ readonly queryPlan: QueryPlan;
20
+ readonly serviceMap: ServiceMap;
21
+ readonly operationContext: OperationContext;
22
+ readonly requestContext: GraphQLRequestContextExecutionDidStart<
23
+ Record<string, any>
24
+ >;
25
+ }) => void;
26
+
27
+ interface ImplementingServiceLocation {
28
+ name: string;
29
+ path: string;
30
+ }
31
+
32
+ export interface CompositionMetadata {
33
+ formatVersion: number;
34
+ id: string;
35
+ implementingServiceLocations: ImplementingServiceLocation[];
36
+ schemaHash: string;
37
+ }
38
+
39
+ export type Experimental_DidFailCompositionCallback = ({
40
+ errors,
41
+ serviceList,
42
+ compositionMetadata,
43
+ }: {
44
+ readonly errors: GraphQLError[];
45
+ readonly serviceList: ServiceDefinition[];
46
+ readonly compositionMetadata?: CompositionMetadata;
47
+ }) => void;
48
+
49
+ export interface ServiceDefinitionCompositionInfo {
50
+ serviceDefinitions: ServiceDefinition[];
51
+ schema: GraphQLSchema;
52
+ compositionMetadata?: CompositionMetadata;
53
+ }
54
+
55
+ export interface SupergraphSdlCompositionInfo {
56
+ schema: GraphQLSchema;
57
+ compositionId: string;
58
+ supergraphSdl: string;
59
+ }
60
+
61
+ export type CompositionInfo =
62
+ | ServiceDefinitionCompositionInfo
63
+ | SupergraphSdlCompositionInfo;
64
+
65
+ export type Experimental_DidUpdateCompositionCallback = (
66
+ currentConfig: CompositionInfo,
67
+ previousConfig?: CompositionInfo,
68
+ ) => void;
69
+
70
+ export type CompositionUpdate = ServiceDefinitionUpdate | SupergraphSdlUpdate;
71
+
72
+ export interface ServiceDefinitionUpdate {
73
+ serviceDefinitions?: ServiceDefinition[];
74
+ compositionMetadata?: CompositionMetadata;
75
+ isNewSchema: boolean;
76
+ }
77
+
78
+ export interface SupergraphSdlUpdate {
79
+ id: string;
80
+ supergraphSdl: string;
81
+ }
82
+
83
+ export function isSupergraphSdlUpdate(update: CompositionUpdate): update is SupergraphSdlUpdate {
84
+ return 'supergraphSdl' in update;
85
+ }
86
+
87
+ export function isServiceDefinitionUpdate(
88
+ update: CompositionUpdate,
89
+ ): update is ServiceDefinitionUpdate {
90
+ return 'isNewSchema' in update;
91
+ }
92
+
93
+ /**
94
+ * **Note:** It's possible for a schema to be the same (`isNewSchema: false`) when
95
+ * `serviceDefinitions` have changed. For example, during type migration, the
96
+ * composed schema may be identical but the `serviceDefinitions` would differ
97
+ * since a type has moved from one service to another.
98
+ */
99
+ export type Experimental_UpdateServiceDefinitions = (
100
+ config: DynamicGatewayConfig,
101
+ ) => Promise<ServiceDefinitionUpdate>;
102
+
103
+ export type Experimental_UpdateSupergraphSdl = (
104
+ config: DynamicGatewayConfig,
105
+ ) => Promise<SupergraphSdlUpdate>;
106
+
107
+ export type Experimental_UpdateComposition = (
108
+ config: DynamicGatewayConfig,
109
+ ) => Promise<CompositionUpdate>;
110
+
111
+ interface GatewayConfigBase {
112
+ debug?: boolean;
113
+ logger?: Logger;
114
+ // TODO: expose the query plan in a more flexible JSON format in the future
115
+ // and remove this config option in favor of `exposeQueryPlan`. Playground
116
+ // should cutover to use the new option when it's built.
117
+ __exposeQueryPlanExperimental?: boolean;
118
+ buildService?: (definition: ServiceEndpointDefinition) => GraphQLDataSource;
119
+
120
+ // experimental observability callbacks
121
+ experimental_didResolveQueryPlan?: Experimental_DidResolveQueryPlanCallback;
122
+ experimental_didFailComposition?: Experimental_DidFailCompositionCallback;
123
+ experimental_didUpdateComposition?: Experimental_DidUpdateCompositionCallback;
124
+ experimental_pollInterval?: number;
125
+ experimental_approximateQueryPlanStoreMiB?: number;
126
+ experimental_autoFragmentization?: boolean;
127
+ fetcher?: typeof fetch;
128
+ serviceHealthCheck?: boolean;
129
+ }
130
+
131
+ export interface RemoteGatewayConfig extends GatewayConfigBase {
132
+ serviceList: ServiceEndpointDefinition[];
133
+ introspectionHeaders?:
134
+ | HeadersInit
135
+ | ((service: ServiceEndpointDefinition) => Promise<HeadersInit> | HeadersInit);
136
+ }
137
+
138
+ export interface ManagedGatewayConfig extends GatewayConfigBase {
139
+ /**
140
+ * This configuration option shouldn't be used unless by recommendation from
141
+ * Apollo staff.
142
+ */
143
+ schemaConfigDeliveryEndpoint?: string; // deprecated
144
+ uplinkEndpoints?: string[];
145
+ uplinkMaxRetries?: number;
146
+ }
147
+
148
+ interface ManuallyManagedServiceDefsGatewayConfig extends GatewayConfigBase {
149
+ experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions;
150
+ }
151
+
152
+ interface ManuallyManagedSupergraphSdlGatewayConfig extends GatewayConfigBase {
153
+ experimental_updateSupergraphSdl: Experimental_UpdateSupergraphSdl
154
+ }
155
+
156
+ type ManuallyManagedGatewayConfig =
157
+ | ManuallyManagedServiceDefsGatewayConfig
158
+ | ManuallyManagedSupergraphSdlGatewayConfig;
159
+
160
+ interface LocalGatewayConfig extends GatewayConfigBase {
161
+ localServiceList: ServiceDefinition[];
162
+ }
163
+
164
+ interface SupergraphSdlGatewayConfig extends GatewayConfigBase {
165
+ supergraphSdl: string;
166
+ }
167
+
168
+ export type StaticGatewayConfig = LocalGatewayConfig | SupergraphSdlGatewayConfig;
169
+
170
+ type DynamicGatewayConfig =
171
+ | ManagedGatewayConfig
172
+ | RemoteGatewayConfig
173
+ | ManuallyManagedGatewayConfig;
174
+
175
+ export type GatewayConfig = StaticGatewayConfig | DynamicGatewayConfig;
176
+
177
+ export function isLocalConfig(config: GatewayConfig): config is LocalGatewayConfig {
178
+ return 'localServiceList' in config;
179
+ }
180
+
181
+ export function isRemoteConfig(config: GatewayConfig): config is RemoteGatewayConfig {
182
+ return 'serviceList' in config;
183
+ }
184
+
185
+ export function isSupergraphSdlConfig(config: GatewayConfig): config is SupergraphSdlGatewayConfig {
186
+ return 'supergraphSdl' in config;
187
+ }
188
+
189
+ // A manually managed config means the user has provided a function which
190
+ // handles providing service definitions to the gateway.
191
+ export function isManuallyManagedConfig(
192
+ config: GatewayConfig,
193
+ ): config is ManuallyManagedGatewayConfig {
194
+ return (
195
+ 'experimental_updateServiceDefinitions' in config ||
196
+ 'experimental_updateSupergraphSdl' in config
197
+ );
198
+ }
199
+
200
+ // Managed config strictly means managed by Studio
201
+ export function isManagedConfig(
202
+ config: GatewayConfig,
203
+ ): config is ManagedGatewayConfig {
204
+ return (
205
+ 'schemaConfigDeliveryEndpoint' in config ||
206
+ (!isRemoteConfig(config) &&
207
+ !isLocalConfig(config) &&
208
+ !isSupergraphSdlConfig(config) &&
209
+ !isManuallyManagedConfig(config))
210
+ );
211
+ }
212
+
213
+ // A static config is one which loads synchronously on start and never updates
214
+ export function isStaticConfig(config: GatewayConfig): config is StaticGatewayConfig {
215
+ return isLocalConfig(config) || isSupergraphSdlConfig(config);
216
+ }
217
+
218
+ // A dynamic config is one which loads asynchronously and (can) update via polling
219
+ export function isDynamicConfig(
220
+ config: GatewayConfig,
221
+ ): config is DynamicGatewayConfig {
222
+ return (
223
+ isRemoteConfig(config) ||
224
+ isManagedConfig(config) ||
225
+ isManuallyManagedConfig(config)
226
+ );
227
+ }
@@ -0,0 +1,412 @@
1
+ import { ApolloGateway } from '../../..';
2
+ import { graphqlErrorSerializer } from 'apollo-federation-integration-testsuite';
3
+
4
+ expect.addSnapshotSerializer(graphqlErrorSerializer);
5
+
6
+ describe('core v0.1', () => {
7
+ it('throws no errors when using a valid @core v0.1 document', () => {
8
+ const supergraphSdl = `#graphql
9
+ schema
10
+ @core(feature: "https://specs.apollo.dev/core/v0.1")
11
+ @core(feature: "https://specs.apollo.dev/join/v0.1") {
12
+ query: Query
13
+ }
14
+
15
+ directive @core(feature: String!) repeatable on SCHEMA
16
+
17
+ directive @join__field(
18
+ graph: join__Graph
19
+ requires: join__FieldSet
20
+ provides: join__FieldSet
21
+ ) on FIELD_DEFINITION
22
+
23
+ directive @join__type(
24
+ graph: join__Graph!
25
+ key: join__FieldSet
26
+ ) repeatable on OBJECT | INTERFACE
27
+
28
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
29
+
30
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
31
+
32
+ directive @tag(
33
+ name: String!
34
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
35
+
36
+ enum CacheControlScope {
37
+ PRIVATE
38
+ PUBLIC
39
+ }
40
+
41
+ scalar join__FieldSet
42
+
43
+ enum join__Graph {
44
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
45
+ }
46
+
47
+ type Query {
48
+ hello: String! @join__field(graph: WORLD)
49
+ }
50
+ `;
51
+
52
+ const gateway = new ApolloGateway({
53
+ supergraphSdl,
54
+ });
55
+
56
+ expect(gateway.load()).resolves.toBeTruthy();
57
+ });
58
+
59
+ it('throws an error when the `for:` @core argument is used in a v0.1 document', () => {
60
+ const supergraphSdl = `#graphql
61
+ schema
62
+ @core(feature: "https://specs.apollo.dev/core/v0.1")
63
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
64
+ @core(
65
+ feature: "https://specs.apollo.dev/something-unsupported/v0.1"
66
+ for: SECURITY
67
+ ) {
68
+ query: Query
69
+ }
70
+
71
+ directive @core(feature: String!) repeatable on SCHEMA
72
+
73
+ directive @join__field(
74
+ graph: join__Graph
75
+ requires: join__FieldSet
76
+ provides: join__FieldSet
77
+ ) on FIELD_DEFINITION
78
+
79
+ directive @join__type(
80
+ graph: join__Graph!
81
+ key: join__FieldSet
82
+ ) repeatable on OBJECT | INTERFACE
83
+
84
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
85
+
86
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
87
+
88
+ directive @tag(
89
+ name: String!
90
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
91
+
92
+ enum CacheControlScope {
93
+ PRIVATE
94
+ PUBLIC
95
+ }
96
+
97
+ scalar join__FieldSet
98
+
99
+ enum join__Graph {
100
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
101
+ }
102
+
103
+ type Query {
104
+ hello: String! @join__field(graph: WORLD)
105
+ }
106
+ `;
107
+
108
+ const gateway = new ApolloGateway({
109
+ supergraphSdl,
110
+ });
111
+
112
+ expect(() => gateway.load()).rejects.toMatchInlineSnapshot(`
113
+ Array [
114
+ "the \`for:\` argument is unsupported by version v0.1 of the core spec. Please upgrade to at least @core v0.2 (https://specs.apollo.dev/core/v0.2).",
115
+ "feature https://specs.apollo.dev/something-unsupported/v0.1 is for: SECURITY but is unsupported",
116
+ ]
117
+ `);
118
+ });
119
+ });
120
+
121
+ describe('core v0.2', () => {
122
+ it("doesn't throw errors when using supported features", async () => {
123
+ const supergraphSdl = `#graphql
124
+ schema
125
+ @core(feature: "https://specs.apollo.dev/core/v0.2")
126
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
127
+ @core(feature: "https://specs.apollo.dev/tag/v0.1") {
128
+ query: Query
129
+ }
130
+
131
+ directive @core(
132
+ feature: String!
133
+ as: String
134
+ for: core__Purpose
135
+ ) repeatable on SCHEMA
136
+
137
+ directive @join__field(
138
+ graph: join__Graph
139
+ requires: join__FieldSet
140
+ provides: join__FieldSet
141
+ ) on FIELD_DEFINITION
142
+
143
+ directive @join__type(
144
+ graph: join__Graph!
145
+ key: join__FieldSet
146
+ ) repeatable on OBJECT | INTERFACE
147
+
148
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
149
+
150
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
151
+
152
+ directive @tag(
153
+ name: String!
154
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
155
+
156
+ enum CacheControlScope {
157
+ PRIVATE
158
+ PUBLIC
159
+ }
160
+
161
+ enum core__Purpose {
162
+ """
163
+ \`EXECUTION\` features provide metadata necessary to for operation execution.
164
+ """
165
+ EXECUTION
166
+
167
+ """
168
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
169
+ """
170
+ SECURITY
171
+ }
172
+
173
+ scalar join__FieldSet
174
+
175
+ enum join__Graph {
176
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
177
+ }
178
+
179
+ type Query {
180
+ hello: String! @join__field(graph: WORLD)
181
+ }
182
+ `;
183
+
184
+ const gateway = new ApolloGateway({
185
+ supergraphSdl,
186
+ });
187
+
188
+ expect(gateway.load()).resolves.toBeTruthy();
189
+ });
190
+
191
+ it("doesn't throw errors when using unsupported features which have no `for:` argument", async () => {
192
+ const supergraphSdl = `#graphql
193
+ schema
194
+ @core(feature: "https://specs.apollo.dev/core/v0.2")
195
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
196
+ @core(feature: "https://specs.apollo.dev/tag/v0.1")
197
+ @core(feature: "https://specs.apollo.dev/unsupported-feature/v0.1") {
198
+ query: Query
199
+ }
200
+
201
+ directive @core(
202
+ feature: String!
203
+ as: String
204
+ for: core__Purpose
205
+ ) repeatable on SCHEMA
206
+
207
+ directive @join__field(
208
+ graph: join__Graph
209
+ requires: join__FieldSet
210
+ provides: join__FieldSet
211
+ ) on FIELD_DEFINITION
212
+
213
+ directive @join__type(
214
+ graph: join__Graph!
215
+ key: join__FieldSet
216
+ ) repeatable on OBJECT | INTERFACE
217
+
218
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
219
+
220
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
221
+
222
+ directive @tag(
223
+ name: String!
224
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
225
+
226
+ enum CacheControlScope {
227
+ PRIVATE
228
+ PUBLIC
229
+ }
230
+
231
+ enum core__Purpose {
232
+ """
233
+ \`EXECUTION\` features provide metadata necessary to for operation execution.
234
+ """
235
+ EXECUTION
236
+
237
+ """
238
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
239
+ """
240
+ SECURITY
241
+ }
242
+
243
+ scalar join__FieldSet
244
+
245
+ enum join__Graph {
246
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
247
+ }
248
+
249
+ type Query {
250
+ hello: String! @join__field(graph: WORLD)
251
+ }
252
+ `;
253
+
254
+ const gateway = new ApolloGateway({
255
+ supergraphSdl,
256
+ });
257
+
258
+ expect(gateway.load()).resolves.toBeTruthy();
259
+ });
260
+
261
+ it('throws errors when using unsupported features for EXECUTION', () => {
262
+ const supergraphSdl = `#graphql
263
+ schema
264
+ @core(feature: "https://specs.apollo.dev/core/v0.2")
265
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
266
+ @core(
267
+ feature: "https://specs.apollo.dev/unsupported-feature/v0.1"
268
+ for: EXECUTION
269
+ ) {
270
+ query: Query
271
+ }
272
+
273
+ directive @core(
274
+ feature: String!
275
+ as: String
276
+ for: core__Purpose
277
+ ) repeatable on SCHEMA
278
+
279
+ directive @join__field(
280
+ graph: join__Graph
281
+ requires: join__FieldSet
282
+ provides: join__FieldSet
283
+ ) on FIELD_DEFINITION
284
+
285
+ directive @join__type(
286
+ graph: join__Graph!
287
+ key: join__FieldSet
288
+ ) repeatable on OBJECT | INTERFACE
289
+
290
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
291
+
292
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
293
+
294
+ directive @tag(
295
+ name: String!
296
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
297
+
298
+ enum CacheControlScope {
299
+ PRIVATE
300
+ PUBLIC
301
+ }
302
+
303
+ enum core__Purpose {
304
+ """
305
+ \`EXECUTION\` features provide metadata necessary to for operation execution.
306
+ """
307
+ EXECUTION
308
+
309
+ """
310
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
311
+ """
312
+ SECURITY
313
+ }
314
+
315
+ scalar join__FieldSet
316
+
317
+ enum join__Graph {
318
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
319
+ }
320
+
321
+ type Query {
322
+ hello: String! @join__field(graph: WORLD)
323
+ }
324
+ `;
325
+
326
+ const gateway = new ApolloGateway({
327
+ supergraphSdl,
328
+ });
329
+
330
+ expect(() => gateway.load()).rejects.toMatchInlineSnapshot(`
331
+ Array [
332
+ "feature https://specs.apollo.dev/unsupported-feature/v0.1 is for: EXECUTION but is unsupported",
333
+ ]
334
+ `);
335
+ });
336
+
337
+ it('throws errors when using unsupported features for SECURITY', async () => {
338
+ const supergraphSdl = `#graphql
339
+ schema
340
+ @core(feature: "https://specs.apollo.dev/core/v0.2")
341
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
342
+ @core(
343
+ feature: "https://specs.apollo.dev/unsupported-feature/v0.1"
344
+ for: SECURITY
345
+ ) {
346
+ query: Query
347
+ }
348
+
349
+ directive @core(
350
+ feature: String!
351
+ as: String
352
+ for: core__Purpose
353
+ ) repeatable on SCHEMA
354
+
355
+ directive @join__field(
356
+ graph: join__Graph
357
+ requires: join__FieldSet
358
+ provides: join__FieldSet
359
+ ) on FIELD_DEFINITION
360
+
361
+ directive @join__type(
362
+ graph: join__Graph!
363
+ key: join__FieldSet
364
+ ) repeatable on OBJECT | INTERFACE
365
+
366
+ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE
367
+
368
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
369
+
370
+ directive @tag(
371
+ name: String!
372
+ ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
373
+
374
+ enum CacheControlScope {
375
+ PRIVATE
376
+ PUBLIC
377
+ }
378
+
379
+ enum core__Purpose {
380
+ """
381
+ \`EXECUTION\` features provide metadata necessary to for operation execution.
382
+ """
383
+ EXECUTION
384
+
385
+ """
386
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
387
+ """
388
+ SECURITY
389
+ }
390
+
391
+ scalar join__FieldSet
392
+
393
+ enum join__Graph {
394
+ WORLD @join__graph(name: "world", url: "https://world.api.com.invalid")
395
+ }
396
+
397
+ type Query {
398
+ hello: String! @join__field(graph: WORLD)
399
+ }
400
+ `;
401
+
402
+ const gateway = new ApolloGateway({
403
+ supergraphSdl,
404
+ });
405
+
406
+ expect(() => gateway.load()).rejects.toMatchInlineSnapshot(`
407
+ Array [
408
+ "feature https://specs.apollo.dev/unsupported-feature/v0.1 is for: SECURITY but is unsupported",
409
+ ]
410
+ `);
411
+ });
412
+ });
@@ -1,4 +1,4 @@
1
- import { GraphQLRequestContext, GraphQLResponse } from 'apollo-server-types';
1
+ import { GraphQLResponse } from 'apollo-server-types';
2
2
  import {
3
3
  GraphQLSchema,
4
4
  graphql,
@@ -6,12 +6,13 @@ import {
6
6
  DocumentNode,
7
7
  parse,
8
8
  } from 'graphql';
9
- import { GraphQLDataSource } from './types';
10
- import {
11
- enablePluginsForSchemaResolvers,
12
- } from 'apollo-server-core/dist/utils/schemaInstrumentation';
9
+ import { enablePluginsForSchemaResolvers } from 'apollo-server-core/dist/utils/schemaInstrumentation';
10
+ import { GraphQLDataSource, GraphQLDataSourceProcessOptions } from './types';
13
11
 
14
- export class LocalGraphQLDataSource<TContext extends Record<string, any> = Record<string, any>> implements GraphQLDataSource<TContext> {
12
+ export class LocalGraphQLDataSource<
13
+ TContext extends Record<string, any> = Record<string, any>,
14
+ > implements GraphQLDataSource<TContext>
15
+ {
15
16
  constructor(public readonly schema: GraphQLSchema) {
16
17
  enablePluginsForSchemaResolvers(schema);
17
18
  }
@@ -19,9 +20,7 @@ export class LocalGraphQLDataSource<TContext extends Record<string, any> = Recor
19
20
  async process({
20
21
  request,
21
22
  context,
22
- }: Pick<GraphQLRequestContext<TContext>, 'request' | 'context'>): Promise<
23
- GraphQLResponse
24
- > {
23
+ }: GraphQLDataSourceProcessOptions<TContext>): Promise<GraphQLResponse> {
25
24
  return graphql({
26
25
  schema: this.schema,
27
26
  source: request.query!,
@@ -37,7 +36,7 @@ export class LocalGraphQLDataSource<TContext extends Record<string, any> = Recor
37
36
  source: `{ _service { sdl }}`,
38
37
  });
39
38
  if (result.errors) {
40
- throw new Error(result.errors.map(error => error.message).join('\n\n'));
39
+ throw new Error(result.errors.map((error) => error.message).join('\n\n'));
41
40
  }
42
41
 
43
42
  const sdl = result.data && result.data._service && result.data._service.sdl;