@apollo/gateway 2.4.4 → 2.4.6
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.
- package/dist/__generated__/graphqlTypes.d.ts +178 -0
- package/dist/__generated__/graphqlTypes.d.ts.map +1 -0
- package/dist/__generated__/graphqlTypes.js +31 -0
- package/dist/__generated__/graphqlTypes.js.map +1 -0
- package/dist/config.d.ts +138 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +60 -0
- package/dist/config.js.map +1 -0
- package/dist/dataRewrites.d.ts +5 -0
- package/dist/dataRewrites.d.ts.map +1 -0
- package/dist/dataRewrites.js +103 -0
- package/dist/dataRewrites.js.map +1 -0
- package/dist/datasources/LocalGraphQLDataSource.d.ts +10 -0
- package/dist/datasources/LocalGraphQLDataSource.d.ts.map +1 -0
- package/dist/datasources/LocalGraphQLDataSource.js +31 -0
- package/dist/datasources/LocalGraphQLDataSource.js.map +1 -0
- package/dist/datasources/RemoteGraphQLDataSource.d.ts +24 -0
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -0
- package/dist/datasources/RemoteGraphQLDataSource.js +180 -0
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -0
- package/dist/datasources/index.d.ts +4 -0
- package/dist/datasources/index.d.ts.map +1 -0
- package/dist/datasources/index.js +8 -0
- package/dist/datasources/index.js.map +1 -0
- package/dist/datasources/parseCacheControlHeader.d.ts +2 -0
- package/dist/datasources/parseCacheControlHeader.d.ts.map +1 -0
- package/dist/datasources/parseCacheControlHeader.js +16 -0
- package/dist/datasources/parseCacheControlHeader.js.map +1 -0
- package/dist/datasources/types.d.ts +23 -0
- package/dist/datasources/types.d.ts.map +1 -0
- package/dist/datasources/types.js +10 -0
- package/dist/datasources/types.js.map +1 -0
- package/dist/executeQueryPlan.d.ts +15 -0
- package/dist/executeQueryPlan.d.ts.map +1 -0
- package/dist/executeQueryPlan.js +539 -0
- package/dist/executeQueryPlan.js.map +1 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +590 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -0
- package/dist/operationContext.d.ts +17 -0
- package/dist/operationContext.d.ts.map +1 -0
- package/dist/operationContext.js +38 -0
- package/dist/operationContext.js.map +1 -0
- package/dist/resultShaping.d.ts +12 -0
- package/dist/resultShaping.d.ts.map +1 -0
- package/dist/resultShaping.js +229 -0
- package/dist/resultShaping.js.map +1 -0
- package/dist/schema-helper/addExtensions.d.ts +3 -0
- package/dist/schema-helper/addExtensions.d.ts.map +1 -0
- package/dist/schema-helper/addExtensions.js +23 -0
- package/dist/schema-helper/addExtensions.js.map +1 -0
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts +31 -0
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts.map +1 -0
- package/dist/supergraphManagers/IntrospectAndCompose/index.js +112 -0
- package/dist/supergraphManagers/IntrospectAndCompose/index.js.map +1 -0
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts +12 -0
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts.map +1 -0
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js +57 -0
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js.map +1 -0
- package/dist/supergraphManagers/LegacyFetcher/index.d.ts +33 -0
- package/dist/supergraphManagers/LegacyFetcher/index.d.ts.map +1 -0
- package/dist/supergraphManagers/LegacyFetcher/index.js +149 -0
- package/dist/supergraphManagers/LegacyFetcher/index.js.map +1 -0
- package/dist/supergraphManagers/LocalCompose/index.d.ts +19 -0
- package/dist/supergraphManagers/LocalCompose/index.d.ts.map +1 -0
- package/dist/supergraphManagers/LocalCompose/index.js +55 -0
- package/dist/supergraphManagers/LocalCompose/index.js.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts +63 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js +210 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts +30 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.js +145 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.js.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts +14 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.js +85 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.js.map +1 -0
- package/dist/supergraphManagers/index.d.ts +6 -0
- package/dist/supergraphManagers/index.d.ts.map +1 -0
- package/dist/supergraphManagers/index.js +27 -0
- package/dist/supergraphManagers/index.js.map +1 -0
- package/dist/typings/graphql.d.ts +11 -0
- package/dist/typings/graphql.d.ts.map +1 -0
- package/dist/typings/graphql.js +3 -0
- package/dist/typings/graphql.js.map +1 -0
- package/dist/utilities/array.d.ts +5 -0
- package/dist/utilities/array.d.ts.map +1 -0
- package/dist/utilities/array.js +46 -0
- package/dist/utilities/array.js.map +1 -0
- package/dist/utilities/assert.d.ts +2 -0
- package/dist/utilities/assert.d.ts.map +1 -0
- package/dist/utilities/assert.js +10 -0
- package/dist/utilities/assert.js.map +1 -0
- package/dist/utilities/deepMerge.d.ts +2 -0
- package/dist/utilities/deepMerge.d.ts.map +1 -0
- package/dist/utilities/deepMerge.js +34 -0
- package/dist/utilities/deepMerge.js.map +1 -0
- package/dist/utilities/graphql.d.ts +5 -0
- package/dist/utilities/graphql.d.ts.map +1 -0
- package/dist/utilities/graphql.js +28 -0
- package/dist/utilities/graphql.js.map +1 -0
- package/dist/utilities/opentelemetry.d.ts +10 -0
- package/dist/utilities/opentelemetry.d.ts.map +1 -0
- package/dist/utilities/opentelemetry.js +19 -0
- package/dist/utilities/opentelemetry.js.map +1 -0
- package/dist/utilities/predicates.d.ts +2 -0
- package/dist/utilities/predicates.d.ts.map +1 -0
- package/dist/utilities/predicates.js +11 -0
- package/dist/utilities/predicates.js.map +1 -0
- package/package.json +4 -4
- package/src/__generated__/graphqlTypes.ts +33 -2
- package/src/__mocks__/tsconfig.json +0 -7
- package/src/__tests__/.gitkeep +0 -0
- package/src/__tests__/CucumberREADME.md +0 -96
- package/src/__tests__/build-query-plan.feature +0 -1471
- package/src/__tests__/buildQueryPlan.test.ts +0 -1225
- package/src/__tests__/executeQueryPlan.conditions.test.ts +0 -1488
- package/src/__tests__/executeQueryPlan.introspection.test.ts +0 -140
- package/src/__tests__/executeQueryPlan.test.ts +0 -6140
- package/src/__tests__/execution-utils.ts +0 -124
- package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +0 -195
- package/src/__tests__/gateway/buildService.test.ts +0 -249
- package/src/__tests__/gateway/endToEnd.test.ts +0 -486
- package/src/__tests__/gateway/executor.test.ts +0 -96
- package/src/__tests__/gateway/extensions.test.ts +0 -37
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +0 -239
- package/src/__tests__/gateway/opentelemetry.test.ts +0 -123
- package/src/__tests__/gateway/queryPlanCache.test.ts +0 -231
- package/src/__tests__/gateway/queryPlannerConfig.test.ts +0 -101
- package/src/__tests__/gateway/reporting.test.ts +0 -616
- package/src/__tests__/gateway/supergraphSdl.test.ts +0 -396
- package/src/__tests__/gateway/testUtils.ts +0 -89
- package/src/__tests__/integration/abstract-types.test.ts +0 -1861
- package/src/__tests__/integration/aliases.test.ts +0 -180
- package/src/__tests__/integration/boolean.test.ts +0 -279
- package/src/__tests__/integration/complex-key.test.ts +0 -197
- package/src/__tests__/integration/configuration.test.ts +0 -404
- package/src/__tests__/integration/custom-directives.test.ts +0 -174
- package/src/__tests__/integration/execution-style.test.ts +0 -35
- package/src/__tests__/integration/fragments.test.ts +0 -237
- package/src/__tests__/integration/list-key.test.ts +0 -128
- package/src/__tests__/integration/logger.test.ts +0 -122
- package/src/__tests__/integration/managed.test.ts +0 -319
- package/src/__tests__/integration/merge-arrays.test.ts +0 -34
- package/src/__tests__/integration/multiple-key.test.ts +0 -327
- package/src/__tests__/integration/mutations.test.ts +0 -287
- package/src/__tests__/integration/networkRequests.test.ts +0 -542
- package/src/__tests__/integration/nockMocks.ts +0 -157
- package/src/__tests__/integration/provides.test.ts +0 -77
- package/src/__tests__/integration/requires.test.ts +0 -359
- package/src/__tests__/integration/scope.test.ts +0 -557
- package/src/__tests__/integration/single-service.test.ts +0 -119
- package/src/__tests__/integration/unions.test.ts +0 -79
- package/src/__tests__/integration/value-types.test.ts +0 -382
- package/src/__tests__/integration/variables.test.ts +0 -120
- package/src/__tests__/nockAssertions.ts +0 -20
- package/src/__tests__/queryPlanCucumber.test.ts +0 -55
- package/src/__tests__/resultShaping.test.ts +0 -605
- package/src/__tests__/testSetup.ts +0 -1
- package/src/__tests__/tsconfig.json +0 -8
- package/src/core/__tests__/core.test.ts +0 -412
- package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +0 -51
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +0 -574
- package/src/schema-helper/__tests__/addExtensions.test.ts +0 -70
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -364
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/loadServicesFromRemoteEndpoint.test.ts +0 -40
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +0 -65
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -511
- package/src/utilities/__tests__/deepMerge.test.ts +0 -77
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag';
|
|
2
|
-
import http from 'http';
|
|
3
|
-
import type { Logger } from '@apollo/utils.logger';
|
|
4
|
-
import { ApolloGateway } from '../..';
|
|
5
|
-
import {
|
|
6
|
-
mockSdlQuerySuccess,
|
|
7
|
-
mockSupergraphSdlRequestSuccess,
|
|
8
|
-
mockApolloConfig,
|
|
9
|
-
mockCloudConfigUrl1,
|
|
10
|
-
} from './nockMocks';
|
|
11
|
-
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
12
|
-
import { fixtures, Fixture } from 'apollo-federation-integration-testsuite';
|
|
13
|
-
|
|
14
|
-
let logger: Logger;
|
|
15
|
-
|
|
16
|
-
const service: Fixture = {
|
|
17
|
-
name: 'accounts',
|
|
18
|
-
url: 'http://localhost:4001',
|
|
19
|
-
typeDefs: gql`
|
|
20
|
-
extend type Query {
|
|
21
|
-
me: User
|
|
22
|
-
everyone: [User]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
"This is my User"
|
|
26
|
-
type User @key(fields: "id") {
|
|
27
|
-
id: ID!
|
|
28
|
-
name: String
|
|
29
|
-
username: String
|
|
30
|
-
}
|
|
31
|
-
`,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
const warn = jest.fn();
|
|
36
|
-
const debug = jest.fn();
|
|
37
|
-
const error = jest.fn();
|
|
38
|
-
const info = jest.fn();
|
|
39
|
-
|
|
40
|
-
logger = {
|
|
41
|
-
warn,
|
|
42
|
-
debug,
|
|
43
|
-
error,
|
|
44
|
-
info,
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('gateway configuration warnings', () => {
|
|
49
|
-
let gateway: ApolloGateway | null = null;
|
|
50
|
-
afterEach(async () => {
|
|
51
|
-
if (gateway) {
|
|
52
|
-
await gateway.stop();
|
|
53
|
-
gateway = null;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
it('warns when both supergraphSdl and studio configuration are provided', async () => {
|
|
57
|
-
gateway = new ApolloGateway({
|
|
58
|
-
supergraphSdl: getTestingSupergraphSdl(),
|
|
59
|
-
logger,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
await gateway.load(mockApolloConfig);
|
|
63
|
-
|
|
64
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
65
|
-
'A local gateway configuration is overriding a managed federation configuration.' +
|
|
66
|
-
' To use the managed configuration, do not specify a service list or supergraphSdl locally.',
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('warns when both manual update configurations are provided', async () => {
|
|
71
|
-
gateway = new ApolloGateway({
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
experimental_updateSupergraphSdl: async () => undefined,
|
|
75
|
-
experimental_updateServiceDefinitions: async () => undefined,
|
|
76
|
-
logger,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
80
|
-
'Gateway found two manual update configurations when only one should be ' +
|
|
81
|
-
'provided. Gateway will default to using the provided `experimental_updateSupergraphSdl` ' +
|
|
82
|
-
'function when both `experimental_updateSupergraphSdl` and experimental_updateServiceDefinitions` ' +
|
|
83
|
-
'are provided.',
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
// Set to `null` so we don't try to call `stop` on it in the `afterEach`,
|
|
87
|
-
// which triggers a different error that we're not testing for here.
|
|
88
|
-
gateway = null;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('conflicting configurations are warned about when present', async () => {
|
|
92
|
-
mockSdlQuerySuccess(service);
|
|
93
|
-
|
|
94
|
-
gateway = new ApolloGateway({
|
|
95
|
-
serviceList: [{ name: 'accounts', url: service.url }],
|
|
96
|
-
logger,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
await gateway.load(mockApolloConfig);
|
|
100
|
-
|
|
101
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
102
|
-
expect.stringMatching(
|
|
103
|
-
/A local gateway configuration is overriding a managed federation configuration/,
|
|
104
|
-
),
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('conflicting configurations are not warned about when absent', async () => {
|
|
109
|
-
mockSupergraphSdlRequestSuccess();
|
|
110
|
-
|
|
111
|
-
gateway = new ApolloGateway({
|
|
112
|
-
logger,
|
|
113
|
-
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
await gateway.load(mockApolloConfig);
|
|
117
|
-
|
|
118
|
-
await gateway.stop();
|
|
119
|
-
|
|
120
|
-
expect(logger.warn).not.toHaveBeenCalledWith(
|
|
121
|
-
expect.stringMatching(
|
|
122
|
-
/A local gateway configuration is overriding a managed federation configuration/,
|
|
123
|
-
),
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('deprecated conflicting configurations are not warned about when absent', async () => {
|
|
128
|
-
mockSupergraphSdlRequestSuccess();
|
|
129
|
-
|
|
130
|
-
gateway = new ApolloGateway({
|
|
131
|
-
logger,
|
|
132
|
-
schemaConfigDeliveryEndpoint: mockCloudConfigUrl1,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
await gateway.load(mockApolloConfig);
|
|
136
|
-
|
|
137
|
-
await gateway.stop();
|
|
138
|
-
|
|
139
|
-
expect(logger.warn).not.toHaveBeenCalledWith(
|
|
140
|
-
expect.stringMatching(
|
|
141
|
-
/A local gateway configuration is overriding a managed federation configuration/,
|
|
142
|
-
),
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('throws when no configuration is provided', async () => {
|
|
147
|
-
gateway = new ApolloGateway({
|
|
148
|
-
logger,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
expect(gateway.load()).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
152
|
-
`"When a manual configuration is not provided, gateway requires an Apollo configuration. See https://www.apollographql.com/docs/apollo-server/federation/managed-federation/ for more information. Manual configuration options include: \`serviceList\`, \`supergraphSdl\`, and \`experimental_updateServiceDefinitions\`."`,
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
// Set to `null` so we don't try to call `stop` on it in the `afterEach`,
|
|
156
|
-
// which triggers a different error that we're not testing for here.
|
|
157
|
-
gateway = null;
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('gateway startup errors', () => {
|
|
162
|
-
it("throws when static config can't be composed", async () => {
|
|
163
|
-
const uncomposableSdl = gql`
|
|
164
|
-
type Query {
|
|
165
|
-
me: User
|
|
166
|
-
everyone: [User]
|
|
167
|
-
account(id: String): Account
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
type User @key(fields: "id") {
|
|
171
|
-
name: String
|
|
172
|
-
username: String
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
type Account @key(fields: "id") {
|
|
176
|
-
name: String
|
|
177
|
-
username: String
|
|
178
|
-
}
|
|
179
|
-
`;
|
|
180
|
-
|
|
181
|
-
const gateway = new ApolloGateway({
|
|
182
|
-
localServiceList: [
|
|
183
|
-
{ name: 'accounts', url: service.url, typeDefs: uncomposableSdl },
|
|
184
|
-
],
|
|
185
|
-
logger,
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
// This is the ideal, but our version of Jest has a bug with printing error snapshots.
|
|
189
|
-
// See: https://github.com/facebook/jest/pull/10217 (fixed in v26.2.0)
|
|
190
|
-
// expect(gateway.load()).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
191
|
-
// "A valid schema couldn't be composed. The following composition errors were found:
|
|
192
|
-
// [accounts] User -> A @key selects id, but User.id could not be found
|
|
193
|
-
// [accounts] Account -> A @key selects id, but Account.id could not be found"
|
|
194
|
-
// `);
|
|
195
|
-
// Instead we'll just use the regular snapshot matcher...
|
|
196
|
-
let err: any;
|
|
197
|
-
try {
|
|
198
|
-
await gateway.load();
|
|
199
|
-
} catch (e) {
|
|
200
|
-
err = e;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const expected =
|
|
204
|
-
"A valid schema couldn't be composed. The following composition errors were found:\n"
|
|
205
|
-
+ ' [accounts] On type "User", for @key(fields: "id"): Cannot query field "id" on type "User" (the field should either be added to this subgraph or, if it should not be resolved by this subgraph, you need to add it to this subgraph with @external).\n'
|
|
206
|
-
+ ' [accounts] On type "Account", for @key(fields: "id"): Cannot query field "id" on type "Account" (the field should either be added to this subgraph or, if it should not be resolved by this subgraph, you need to add it to this subgraph with @external).'
|
|
207
|
-
expect(err.message).toBe(expected);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
describe('gateway config / env behavior', () => {
|
|
212
|
-
let gateway: ApolloGateway | null = null;
|
|
213
|
-
let cleanUp: (() => void) | null = null;
|
|
214
|
-
afterEach(async () => {
|
|
215
|
-
if (gateway) {
|
|
216
|
-
await gateway.stop();
|
|
217
|
-
gateway = null;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (cleanUp) {
|
|
221
|
-
cleanUp();
|
|
222
|
-
cleanUp = null;
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
describe('introspection headers', () => {
|
|
227
|
-
it('should allow not passing introspectionHeaders', async () => {
|
|
228
|
-
const receivedHeaders = jest.fn();
|
|
229
|
-
const nock = mockSdlQuerySuccess(service);
|
|
230
|
-
nock.on('request', (req: http.ClientRequest) =>
|
|
231
|
-
receivedHeaders(req.getHeaders()),
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
gateway = new ApolloGateway({
|
|
235
|
-
serviceList: [{ name: 'accounts', url: service.url }],
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
await gateway.load(mockApolloConfig);
|
|
239
|
-
|
|
240
|
-
expect(receivedHeaders).toHaveBeenCalledWith(
|
|
241
|
-
expect.objectContaining({
|
|
242
|
-
host: 'localhost:4001',
|
|
243
|
-
}),
|
|
244
|
-
);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should use static headers', async () => {
|
|
248
|
-
const receivedHeaders = jest.fn();
|
|
249
|
-
const nock = mockSdlQuerySuccess(service);
|
|
250
|
-
nock.on('request', (req: http.ClientRequest) =>
|
|
251
|
-
receivedHeaders(req.getHeaders()),
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
gateway = new ApolloGateway({
|
|
255
|
-
serviceList: [{ name: 'accounts', url: service.url }],
|
|
256
|
-
introspectionHeaders: {
|
|
257
|
-
Authorization: 'Bearer static',
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
await gateway.load(mockApolloConfig);
|
|
262
|
-
|
|
263
|
-
expect(receivedHeaders).toHaveBeenCalledWith(
|
|
264
|
-
expect.objectContaining({
|
|
265
|
-
authorization: ['Bearer static'],
|
|
266
|
-
}),
|
|
267
|
-
);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it('should use dynamic async headers', async () => {
|
|
271
|
-
const receivedHeaders = jest.fn();
|
|
272
|
-
const nock = mockSdlQuerySuccess(service);
|
|
273
|
-
nock.on('request', (req: http.ClientRequest) =>
|
|
274
|
-
receivedHeaders(req.getHeaders()),
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
gateway = new ApolloGateway({
|
|
278
|
-
serviceList: [{ name: 'accounts', url: service.url }],
|
|
279
|
-
introspectionHeaders: async ({ name }) => ({
|
|
280
|
-
Authorization: 'Bearer dynamic-async',
|
|
281
|
-
'X-Service-Name': name,
|
|
282
|
-
}),
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
await gateway.load(mockApolloConfig);
|
|
286
|
-
|
|
287
|
-
expect(receivedHeaders).toHaveBeenCalledWith(
|
|
288
|
-
expect.objectContaining({
|
|
289
|
-
authorization: ['Bearer dynamic-async'],
|
|
290
|
-
'x-service-name': ['accounts'],
|
|
291
|
-
}),
|
|
292
|
-
);
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it('should use dynamic non-async headers', async () => {
|
|
296
|
-
const receivedHeaders = jest.fn();
|
|
297
|
-
const nock = mockSdlQuerySuccess(service);
|
|
298
|
-
nock.on('request', (req: http.ClientRequest) =>
|
|
299
|
-
receivedHeaders(req.getHeaders()),
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
gateway = new ApolloGateway({
|
|
303
|
-
serviceList: [{ name: 'accounts', url: service.url }],
|
|
304
|
-
introspectionHeaders: ({ name }) => ({
|
|
305
|
-
Authorization: 'Bearer dynamic-sync',
|
|
306
|
-
'X-Service-Name': name,
|
|
307
|
-
}),
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
await gateway.load(mockApolloConfig);
|
|
311
|
-
|
|
312
|
-
expect(receivedHeaders).toHaveBeenCalledWith(
|
|
313
|
-
expect.objectContaining({
|
|
314
|
-
authorization: ['Bearer dynamic-sync'],
|
|
315
|
-
'x-service-name': ['accounts'],
|
|
316
|
-
}),
|
|
317
|
-
);
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
describe('deprecation warnings', () => {
|
|
323
|
-
it('warns with `experimental_updateSupergraphSdl` option set', async () => {
|
|
324
|
-
const gateway = new ApolloGateway({
|
|
325
|
-
async experimental_updateSupergraphSdl() {
|
|
326
|
-
return {
|
|
327
|
-
id: 'supergraph',
|
|
328
|
-
supergraphSdl: getTestingSupergraphSdl(),
|
|
329
|
-
};
|
|
330
|
-
},
|
|
331
|
-
logger,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
await gateway.load();
|
|
335
|
-
|
|
336
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
337
|
-
'The `experimental_updateSupergraphSdl` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the function form of the `supergraphSdl` configuration option.',
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
await gateway.stop();
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('warns with `experimental_updateServiceDefinitions` option set', async () => {
|
|
344
|
-
const gateway = new ApolloGateway({
|
|
345
|
-
async experimental_updateServiceDefinitions() {
|
|
346
|
-
return {
|
|
347
|
-
isNewSchema: false,
|
|
348
|
-
};
|
|
349
|
-
},
|
|
350
|
-
logger,
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
await gateway.load();
|
|
355
|
-
// gateway will throw since we're not providing an actual service list, disregard
|
|
356
|
-
} catch {}
|
|
357
|
-
|
|
358
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
359
|
-
'The `experimental_updateServiceDefinitions` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the function form of the `supergraphSdl` configuration option.',
|
|
360
|
-
);
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
it('warns with `serviceList` option set', async () => {
|
|
364
|
-
const gateway = new ApolloGateway({
|
|
365
|
-
serviceList: [{ name: 'accounts', url: 'http://localhost:4001' }],
|
|
366
|
-
logger,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
try {
|
|
370
|
-
await gateway.load();
|
|
371
|
-
// gateway will throw since we haven't mocked these requests, unimportant for this test
|
|
372
|
-
} catch {}
|
|
373
|
-
|
|
374
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
375
|
-
'The `serviceList` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to its replacement `IntrospectAndCompose`. More information on `IntrospectAndCompose` can be found in the documentation.',
|
|
376
|
-
);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
it('warns with `localServiceList` option set', async () => {
|
|
380
|
-
const gateway = new ApolloGateway({
|
|
381
|
-
localServiceList: fixtures,
|
|
382
|
-
logger,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
await gateway.load();
|
|
386
|
-
|
|
387
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
388
|
-
'The `localServiceList` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the `LocalCompose` supergraph manager exported by `@apollo/gateway`.',
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
await gateway.stop();
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
it('warns with `schemaConfigDeliveryEndpoint` option set', async () => {
|
|
395
|
-
new ApolloGateway({
|
|
396
|
-
schemaConfigDeliveryEndpoint: 'test',
|
|
397
|
-
logger,
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
expect(logger.warn).toHaveBeenCalledWith(
|
|
401
|
-
'The `schemaConfigDeliveryEndpoint` option is deprecated and will be removed in a future version of `@apollo/gateway`. Please migrate to the equivalent (array form) `uplinkEndpoints` configuration option.',
|
|
402
|
-
);
|
|
403
|
-
});
|
|
404
|
-
});
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag';
|
|
2
|
-
import { execute } from '../execution-utils';
|
|
3
|
-
import {
|
|
4
|
-
astSerializer,
|
|
5
|
-
queryPlanSerializer,
|
|
6
|
-
} from 'apollo-federation-integration-testsuite';
|
|
7
|
-
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
8
|
-
|
|
9
|
-
expect.addSnapshotSerializer(astSerializer);
|
|
10
|
-
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
11
|
-
|
|
12
|
-
describe('custom executable directives', () => {
|
|
13
|
-
it('successfully passes directives along in requests to an underlying service', async () => {
|
|
14
|
-
const query = `#graphql
|
|
15
|
-
query GetReviewers {
|
|
16
|
-
topReviews {
|
|
17
|
-
body @stream
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
const { errors, queryPlan } = await execute({
|
|
23
|
-
query,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
expect(errors).toBeUndefined();
|
|
27
|
-
expect(queryPlan).toCallService('reviews');
|
|
28
|
-
expect(queryPlan).toMatchInlineSnapshot(`
|
|
29
|
-
QueryPlan {
|
|
30
|
-
Fetch(service: "reviews") {
|
|
31
|
-
{
|
|
32
|
-
topReviews {
|
|
33
|
-
body @stream
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
}
|
|
38
|
-
`);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('successfully passes directives and their variables along in requests to underlying services', async () => {
|
|
42
|
-
const query = `#graphql
|
|
43
|
-
query GetReviewers {
|
|
44
|
-
topReviews {
|
|
45
|
-
body @stream
|
|
46
|
-
author @transform(from: "JSON") {
|
|
47
|
-
name @stream {
|
|
48
|
-
first
|
|
49
|
-
last
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
const { errors, queryPlan } = await execute({
|
|
57
|
-
query,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
expect(errors).toBeUndefined();
|
|
61
|
-
expect(queryPlan).toCallService('reviews');
|
|
62
|
-
expect(queryPlan).toCallService('accounts');
|
|
63
|
-
expect(queryPlan).toMatchInlineSnapshot(`
|
|
64
|
-
QueryPlan {
|
|
65
|
-
Sequence {
|
|
66
|
-
Fetch(service: "reviews") {
|
|
67
|
-
{
|
|
68
|
-
topReviews {
|
|
69
|
-
body @stream
|
|
70
|
-
author @transform(from: "JSON") {
|
|
71
|
-
__typename
|
|
72
|
-
id
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
Flatten(path: "topReviews.@.author") {
|
|
78
|
-
Fetch(service: "accounts") {
|
|
79
|
-
{
|
|
80
|
-
... on User {
|
|
81
|
-
__typename
|
|
82
|
-
id
|
|
83
|
-
}
|
|
84
|
-
} =>
|
|
85
|
-
{
|
|
86
|
-
... on User {
|
|
87
|
-
name @stream {
|
|
88
|
-
first
|
|
89
|
-
last
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
-
`);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// With relaxed composition, instead of erroring out if a directive is not declared everywhere, we compose but don't
|
|
101
|
-
// include the directive in the supergraph and generate a hint. So the following test will complain that @stream
|
|
102
|
-
// is unknown in the query. Not that the hints tests do test we properly raise an hint in that case.
|
|
103
|
-
it.skip("returns validation errors when directives aren't present across all services", async () => {
|
|
104
|
-
const invalidService = {
|
|
105
|
-
name: 'invalidService',
|
|
106
|
-
typeDefs: gql`
|
|
107
|
-
directive @invalid on QUERY
|
|
108
|
-
`,
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const query = `#graphql
|
|
112
|
-
query GetReviewers {
|
|
113
|
-
topReviews {
|
|
114
|
-
body @stream
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
`;
|
|
118
|
-
|
|
119
|
-
expect(
|
|
120
|
-
execute(
|
|
121
|
-
{
|
|
122
|
-
query,
|
|
123
|
-
},
|
|
124
|
-
[...fixtures, invalidService],
|
|
125
|
-
),
|
|
126
|
-
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
127
|
-
"[@invalid] -> Custom directives must be implemented in every service. The following services do not implement the @invalid directive: accounts, books, documents, inventory, product, reviews.
|
|
128
|
-
|
|
129
|
-
[@stream] -> Custom directives must be implemented in every service. The following services do not implement the @stream directive: invalidService.
|
|
130
|
-
|
|
131
|
-
[@transform] -> Custom directives must be implemented in every service. The following services do not implement the @transform directive: invalidService."
|
|
132
|
-
`);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Same as previous: we don't of error out on inconsistent execution directives. Here, we instead look at the intersection of locations
|
|
136
|
-
// defined, and as that is empty, we don't include the directive in the supergraph (and raise a hint).
|
|
137
|
-
// So the following test will complain that @stream is unknown in the query. Not that the hints tests do test we properly raise an hint in that case.
|
|
138
|
-
it.skip("returns validation errors when directives aren't identical across all services", async () => {
|
|
139
|
-
const invalidService = {
|
|
140
|
-
name: 'invalid',
|
|
141
|
-
typeDefs: gql`
|
|
142
|
-
directive @stream on QUERY
|
|
143
|
-
`,
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const query = `#graphql
|
|
147
|
-
query GetReviewers {
|
|
148
|
-
topReviews {
|
|
149
|
-
body @stream
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
`;
|
|
153
|
-
|
|
154
|
-
expect(
|
|
155
|
-
execute(
|
|
156
|
-
{
|
|
157
|
-
query,
|
|
158
|
-
},
|
|
159
|
-
[...fixtures, invalidService],
|
|
160
|
-
),
|
|
161
|
-
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
162
|
-
"[@transform] -> Custom directives must be implemented in every service. The following services do not implement the @transform directive: invalid.
|
|
163
|
-
|
|
164
|
-
[@stream] -> custom directives must be defined identically across all services. See below for a list of current implementations:
|
|
165
|
-
accounts: directive @stream on FIELD
|
|
166
|
-
books: directive @stream on FIELD
|
|
167
|
-
documents: directive @stream on FIELD
|
|
168
|
-
inventory: directive @stream on FIELD
|
|
169
|
-
product: directive @stream on FIELD
|
|
170
|
-
reviews: directive @stream on FIELD
|
|
171
|
-
invalid: directive @stream on QUERY"
|
|
172
|
-
`);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { execute } from '../execution-utils';
|
|
2
|
-
|
|
3
|
-
describe('query', () => {
|
|
4
|
-
it('supports parallel root fields', async () => {
|
|
5
|
-
const query = `#graphql
|
|
6
|
-
query GetUserAndReviews {
|
|
7
|
-
me {
|
|
8
|
-
username
|
|
9
|
-
}
|
|
10
|
-
topReviews {
|
|
11
|
-
body
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
`;
|
|
15
|
-
|
|
16
|
-
const { data, queryPlan } = await execute({
|
|
17
|
-
query,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
expect(data).toEqual({
|
|
21
|
-
me: { username: '@ada' },
|
|
22
|
-
topReviews: [
|
|
23
|
-
{ body: 'Love it!' },
|
|
24
|
-
{ body: 'Too expensive.' },
|
|
25
|
-
{ body: 'Could be better.' },
|
|
26
|
-
{ body: 'Prefer something else.' },
|
|
27
|
-
{ body: 'Wish I had read this before.' },
|
|
28
|
-
],
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
expect(queryPlan).toCallService('accounts');
|
|
32
|
-
expect(queryPlan).toCallService('reviews');
|
|
33
|
-
// FIXME: determine matcher for execution order
|
|
34
|
-
});
|
|
35
|
-
});
|