@apollo/gateway 2.4.0-alpha.1 → 2.4.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.
- package/dist/__generated__/graphqlTypes.d.ts +1 -0
- package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
- package/dist/__generated__/graphqlTypes.js.map +1 -1
- 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/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +41 -110
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/resultShaping.js +3 -3
- package/dist/resultShaping.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js.map +1 -1
- package/package.json +4 -4
- package/src/__generated__/graphqlTypes.ts +4 -3
- package/src/__tests__/buildQueryPlan.test.ts +0 -1
- package/src/__tests__/executeQueryPlan.introspection.test.ts +140 -0
- package/src/__tests__/executeQueryPlan.test.ts +269 -5
- package/src/__tests__/gateway/buildService.test.ts +2 -2
- package/src/__tests__/gateway/supergraphSdl.test.ts +2 -2
- package/src/__tests__/integration/complex-key.test.ts +4 -4
- package/src/__tests__/integration/list-key.test.ts +2 -2
- package/src/__tests__/integration/multiple-key.test.ts +2 -2
- package/src/__tests__/integration/requires.test.ts +2 -2
- package/src/__tests__/integration/single-service.test.ts +1 -1
- package/src/__tests__/integration/value-types.test.ts +13 -16
- package/src/dataRewrites.ts +130 -0
- package/src/executeQueryPlan.ts +57 -135
- package/src/resultShaping.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/gateway",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Apollo Gateway",
|
|
5
5
|
"author": "Apollo <packages@apollographql.com>",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@apollo/composition": "2.4.
|
|
29
|
-
"@apollo/federation-internals": "2.4.
|
|
30
|
-
"@apollo/query-planner": "2.4.
|
|
28
|
+
"@apollo/composition": "2.4.1",
|
|
29
|
+
"@apollo/federation-internals": "2.4.1",
|
|
30
|
+
"@apollo/query-planner": "2.4.1",
|
|
31
31
|
"@apollo/server-gateway-interface": "^1.1.0",
|
|
32
32
|
"@apollo/usage-reporting-protobuf": "^4.1.0",
|
|
33
33
|
"@apollo/utils.createhash": "^2.0.0",
|
|
@@ -51,11 +51,11 @@ export type FetchError = {
|
|
|
51
51
|
export enum FetchErrorCode {
|
|
52
52
|
/** This token does not have access to fetch the schema for this ref. Do not retry. */
|
|
53
53
|
AccessDenied = 'ACCESS_DENIED',
|
|
54
|
-
/** This token provided is not a valid graph token. Do not retry */
|
|
54
|
+
/** This token provided is not a valid graph token. Do not retry. */
|
|
55
55
|
AuthenticationFailed = 'AUTHENTICATION_FAILED',
|
|
56
|
-
/** An internal server error occurred. Please retry with some backoff */
|
|
56
|
+
/** An internal server error occurred. Please retry with some backoff. */
|
|
57
57
|
RetryLater = 'RETRY_LATER',
|
|
58
|
-
/** The graphRef passed is not a valid ref or no configuration for that ref is found.
|
|
58
|
+
/** The graphRef passed is not a valid ref or no configuration for that ref is found. Please retry with some backoff, eg in case of undeletion. */
|
|
59
59
|
UnknownRef = 'UNKNOWN_REF'
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -105,6 +105,7 @@ export type QueryRouterConfigArgs = {
|
|
|
105
105
|
|
|
106
106
|
export type QueryRouterEntitlementsArgs = {
|
|
107
107
|
apiKey: Scalars['String'];
|
|
108
|
+
ifAfterId?: InputMaybe<Scalars['ID']>;
|
|
108
109
|
ref: Scalars['String'];
|
|
109
110
|
unlessId?: InputMaybe<Scalars['ID']>;
|
|
110
111
|
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import gql from 'graphql-tag';
|
|
2
|
+
import { getFederatedTestingSchema, ServiceDefinitionModule } from './execution-utils';
|
|
3
|
+
import { Operation, parseOperation, Schema } from "@apollo/federation-internals";
|
|
4
|
+
import { QueryPlan } from '@apollo/query-planner';
|
|
5
|
+
import { LocalGraphQLDataSource } from '../datasources';
|
|
6
|
+
import { GatewayExecutionResult, GatewayGraphQLRequestContext } from '@apollo/server-gateway-interface';
|
|
7
|
+
import { buildOperationContext } from '../operationContext';
|
|
8
|
+
import { executeQueryPlan } from '../executeQueryPlan';
|
|
9
|
+
|
|
10
|
+
function buildRequestContext(variables: Record<string, any>): GatewayGraphQLRequestContext {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
return {
|
|
14
|
+
cache: undefined as any,
|
|
15
|
+
context: {},
|
|
16
|
+
request: {
|
|
17
|
+
variables,
|
|
18
|
+
},
|
|
19
|
+
metrics: {},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function executePlan(
|
|
24
|
+
queryPlan: QueryPlan,
|
|
25
|
+
operation: Operation,
|
|
26
|
+
schema: Schema,
|
|
27
|
+
serviceMap: { [serviceName: string]: LocalGraphQLDataSource },
|
|
28
|
+
variables: Record<string, any> = {},
|
|
29
|
+
): Promise<GatewayExecutionResult> {
|
|
30
|
+
const apiSchema = schema.toAPISchema();
|
|
31
|
+
const operationContext = buildOperationContext({
|
|
32
|
+
schema: apiSchema.toGraphQLJSSchema(),
|
|
33
|
+
operationDocument: gql`${operation.toString()}`,
|
|
34
|
+
});
|
|
35
|
+
return executeQueryPlan(
|
|
36
|
+
queryPlan,
|
|
37
|
+
serviceMap,
|
|
38
|
+
buildRequestContext(variables),
|
|
39
|
+
operationContext,
|
|
40
|
+
schema.toGraphQLJSSchema(),
|
|
41
|
+
apiSchema,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('handling of introspection queries', () => {
|
|
46
|
+
const typeDefs: ServiceDefinitionModule[] = [
|
|
47
|
+
{
|
|
48
|
+
name: 'S1',
|
|
49
|
+
typeDefs: gql`
|
|
50
|
+
type Query {
|
|
51
|
+
t: [T]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface T {
|
|
55
|
+
id: ID!
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type T1 implements T @key(fields: "id") {
|
|
59
|
+
id: ID!
|
|
60
|
+
a1: Int
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type T2 implements T @key(fields: "id") {
|
|
64
|
+
id: ID!
|
|
65
|
+
a2: Int
|
|
66
|
+
}
|
|
67
|
+
`,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema(typeDefs);
|
|
71
|
+
|
|
72
|
+
it('it handles aliases on introspection fields', async () => {
|
|
73
|
+
const operation = parseOperation(schema, `
|
|
74
|
+
{
|
|
75
|
+
myAlias: __type(name: "T1") {
|
|
76
|
+
kind
|
|
77
|
+
name
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`);
|
|
81
|
+
|
|
82
|
+
const queryPlan = queryPlanner.buildQueryPlan(operation);
|
|
83
|
+
const response = await executePlan(queryPlan, operation, schema, serviceMap);
|
|
84
|
+
expect(response.errors).toBeUndefined();
|
|
85
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
86
|
+
Object {
|
|
87
|
+
"myAlias": Object {
|
|
88
|
+
"kind": "OBJECT",
|
|
89
|
+
"name": "T1",
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('it handles aliases inside introspection fields', async () => {
|
|
96
|
+
const operation = parseOperation(schema, `
|
|
97
|
+
{
|
|
98
|
+
__type(name: "T1") {
|
|
99
|
+
myKind: kind
|
|
100
|
+
name
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
`);
|
|
104
|
+
|
|
105
|
+
const queryPlan = queryPlanner.buildQueryPlan(operation);
|
|
106
|
+
const response = await executePlan(queryPlan, operation, schema, serviceMap);
|
|
107
|
+
expect(response.errors).toBeUndefined();
|
|
108
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
109
|
+
Object {
|
|
110
|
+
"__type": Object {
|
|
111
|
+
"myKind": "OBJECT",
|
|
112
|
+
"name": "T1",
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
`);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('it handles variables passed to introspection fields', async () => {
|
|
119
|
+
const operation = parseOperation(schema, `
|
|
120
|
+
query ($name: String!) {
|
|
121
|
+
__type(name: $name) {
|
|
122
|
+
kind
|
|
123
|
+
name
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
`);
|
|
127
|
+
|
|
128
|
+
const queryPlan = queryPlanner.buildQueryPlan(operation);
|
|
129
|
+
const response = await executePlan(queryPlan, operation, schema, serviceMap, { name: "T1" });
|
|
130
|
+
expect(response.errors).toBeUndefined();
|
|
131
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
132
|
+
Object {
|
|
133
|
+
"__type": Object {
|
|
134
|
+
"kind": "OBJECT",
|
|
135
|
+
"name": "T1",
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
`);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -3165,7 +3165,8 @@ describe('executeQueryPlan', () => {
|
|
|
3165
3165
|
data {
|
|
3166
3166
|
__typename
|
|
3167
3167
|
foo
|
|
3168
|
-
... on
|
|
3168
|
+
... on Bar {
|
|
3169
|
+
__typename
|
|
3169
3170
|
bar
|
|
3170
3171
|
}
|
|
3171
3172
|
}
|
|
@@ -3829,7 +3830,7 @@ describe('executeQueryPlan', () => {
|
|
|
3829
3830
|
name: 'S1',
|
|
3830
3831
|
typeDefs: gql`
|
|
3831
3832
|
extend schema
|
|
3832
|
-
@link(url: "https://specs.apollo.dev/federation/v2.
|
|
3833
|
+
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
|
3833
3834
|
|
|
3834
3835
|
type Query {
|
|
3835
3836
|
iFromS1: I
|
|
@@ -3875,7 +3876,7 @@ describe('executeQueryPlan', () => {
|
|
|
3875
3876
|
name: 'S2',
|
|
3876
3877
|
typeDefs: gql`
|
|
3877
3878
|
extend schema
|
|
3878
|
-
@link(url: "https://specs.apollo.dev/federation/v2.
|
|
3879
|
+
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@interfaceObject"])
|
|
3879
3880
|
|
|
3880
3881
|
type Query {
|
|
3881
3882
|
iFromS2: I
|
|
@@ -4341,7 +4342,7 @@ describe('executeQueryPlan', () => {
|
|
|
4341
4342
|
name: 'products',
|
|
4342
4343
|
typeDefs: gql`
|
|
4343
4344
|
extend schema
|
|
4344
|
-
@link(url: "https://specs.apollo.dev/federation/v2.
|
|
4345
|
+
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
|
4345
4346
|
|
|
4346
4347
|
type Query {
|
|
4347
4348
|
products: [Product!]!
|
|
@@ -4390,7 +4391,7 @@ describe('executeQueryPlan', () => {
|
|
|
4390
4391
|
name: 'reviews',
|
|
4391
4392
|
typeDefs: gql`
|
|
4392
4393
|
extend schema
|
|
4393
|
-
@link(url: "https://specs.apollo.dev/federation/v2.
|
|
4394
|
+
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@interfaceObject"])
|
|
4394
4395
|
|
|
4395
4396
|
type Query {
|
|
4396
4397
|
allReviewedProducts: [Product!]!
|
|
@@ -4599,6 +4600,269 @@ describe('executeQueryPlan', () => {
|
|
|
4599
4600
|
}
|
|
4600
4601
|
`);
|
|
4601
4602
|
});
|
|
4603
|
+
|
|
4604
|
+
test('handles querying @interfaceObject from a specific implementation', async () => {
|
|
4605
|
+
const s1 = {
|
|
4606
|
+
name: 's1',
|
|
4607
|
+
typeDefs: gql`
|
|
4608
|
+
extend schema
|
|
4609
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key"])
|
|
4610
|
+
|
|
4611
|
+
type Query {
|
|
4612
|
+
ts: [T!]!
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
interface I {
|
|
4616
|
+
id: ID!
|
|
4617
|
+
}
|
|
4618
|
+
|
|
4619
|
+
type T implements I @key(fields: "id") {
|
|
4620
|
+
id: ID!
|
|
4621
|
+
}
|
|
4622
|
+
`,
|
|
4623
|
+
resolvers: {
|
|
4624
|
+
Query: {
|
|
4625
|
+
ts: () => [ { id: '2' }, { id: '4' }, { id: '1' } ]
|
|
4626
|
+
},
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
|
|
4630
|
+
const s2 = {
|
|
4631
|
+
name: 's2',
|
|
4632
|
+
typeDefs: gql`
|
|
4633
|
+
extend schema
|
|
4634
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key", "@interfaceObject", "@external", "@requires"])
|
|
4635
|
+
|
|
4636
|
+
type I @key(fields: "id") @interfaceObject {
|
|
4637
|
+
id: ID!
|
|
4638
|
+
v: String
|
|
4639
|
+
}
|
|
4640
|
+
`,
|
|
4641
|
+
resolvers: {
|
|
4642
|
+
I: {
|
|
4643
|
+
__resolveReference(ref: any) {
|
|
4644
|
+
return {
|
|
4645
|
+
...ref,
|
|
4646
|
+
v: `id=${ref.id}`
|
|
4647
|
+
};
|
|
4648
|
+
},
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
|
|
4653
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2 ]);
|
|
4654
|
+
|
|
4655
|
+
let operation = parseOp(`
|
|
4656
|
+
{
|
|
4657
|
+
ts {
|
|
4658
|
+
v
|
|
4659
|
+
}
|
|
4660
|
+
}
|
|
4661
|
+
`, schema);
|
|
4662
|
+
|
|
4663
|
+
let queryPlan = buildPlan(operation, queryPlanner);
|
|
4664
|
+
const expectedPlan = `
|
|
4665
|
+
QueryPlan {
|
|
4666
|
+
Sequence {
|
|
4667
|
+
Fetch(service: "s1") {
|
|
4668
|
+
{
|
|
4669
|
+
ts {
|
|
4670
|
+
__typename
|
|
4671
|
+
id
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4674
|
+
},
|
|
4675
|
+
Flatten(path: "ts.@") {
|
|
4676
|
+
Fetch(service: "s2") {
|
|
4677
|
+
{
|
|
4678
|
+
... on T {
|
|
4679
|
+
__typename
|
|
4680
|
+
id
|
|
4681
|
+
}
|
|
4682
|
+
} =>
|
|
4683
|
+
{
|
|
4684
|
+
... on I {
|
|
4685
|
+
v
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
},
|
|
4689
|
+
},
|
|
4690
|
+
},
|
|
4691
|
+
}
|
|
4692
|
+
`;
|
|
4693
|
+
expect(queryPlan).toMatchInlineSnapshot(expectedPlan);
|
|
4694
|
+
|
|
4695
|
+
let response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
4696
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
4697
|
+
Object {
|
|
4698
|
+
"ts": Array [
|
|
4699
|
+
Object {
|
|
4700
|
+
"v": "id=2",
|
|
4701
|
+
},
|
|
4702
|
+
Object {
|
|
4703
|
+
"v": "id=4",
|
|
4704
|
+
},
|
|
4705
|
+
Object {
|
|
4706
|
+
"v": "id=1",
|
|
4707
|
+
},
|
|
4708
|
+
],
|
|
4709
|
+
}
|
|
4710
|
+
`);
|
|
4711
|
+
});
|
|
4712
|
+
|
|
4713
|
+
test('handles querying @interfaceObject from a specific implementation (even when the subgraph does not have the corresponding interface)', async () => {
|
|
4714
|
+
const s1 = {
|
|
4715
|
+
name: 's1',
|
|
4716
|
+
typeDefs: gql`
|
|
4717
|
+
extend schema
|
|
4718
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key"])
|
|
4719
|
+
|
|
4720
|
+
type Query {
|
|
4721
|
+
ts: [T!]!
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4724
|
+
type T @key(fields: "id", resolvable: false) {
|
|
4725
|
+
id: ID!
|
|
4726
|
+
}
|
|
4727
|
+
`,
|
|
4728
|
+
resolvers: {
|
|
4729
|
+
Query: {
|
|
4730
|
+
ts: () => [ { id: '2' }, { id: '4' }, { id: '1' } ]
|
|
4731
|
+
},
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
const s2 = {
|
|
4736
|
+
name: 's2',
|
|
4737
|
+
typeDefs: gql`
|
|
4738
|
+
extend schema
|
|
4739
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key", "@interfaceObject"])
|
|
4740
|
+
|
|
4741
|
+
interface I @key(fields: "id") {
|
|
4742
|
+
id: ID!
|
|
4743
|
+
required: String
|
|
4744
|
+
}
|
|
4745
|
+
|
|
4746
|
+
type T implements I @key(fields: "id") {
|
|
4747
|
+
id: ID!
|
|
4748
|
+
required: String
|
|
4749
|
+
}
|
|
4750
|
+
|
|
4751
|
+
`,
|
|
4752
|
+
resolvers: {
|
|
4753
|
+
I: {
|
|
4754
|
+
__resolveReference(ref: any) {
|
|
4755
|
+
return [
|
|
4756
|
+
{ id: '1', __typename: "T", required: "r1" },
|
|
4757
|
+
{ id: '2', __typename: "T", required: "r2" },
|
|
4758
|
+
{ id: '3', __typename: "T", required: "r3" },
|
|
4759
|
+
{ id: '4', __typename: "T", required: "r4" },
|
|
4760
|
+
].find(({id}) => id === ref.id);
|
|
4761
|
+
},
|
|
4762
|
+
},
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
|
|
4766
|
+
const s3 = {
|
|
4767
|
+
name: 's3',
|
|
4768
|
+
typeDefs: gql`
|
|
4769
|
+
extend schema
|
|
4770
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key", "@interfaceObject", "@external", "@requires"])
|
|
4771
|
+
|
|
4772
|
+
type I @key(fields: "id") @interfaceObject {
|
|
4773
|
+
id: ID!
|
|
4774
|
+
required: String @external
|
|
4775
|
+
v: String @requires(fields: "required")
|
|
4776
|
+
}
|
|
4777
|
+
`,
|
|
4778
|
+
resolvers: {
|
|
4779
|
+
I: {
|
|
4780
|
+
__resolveReference(ref: any) {
|
|
4781
|
+
return {
|
|
4782
|
+
...ref,
|
|
4783
|
+
v: `req=${ref.required}`
|
|
4784
|
+
};
|
|
4785
|
+
},
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
|
|
4790
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2, s3 ]);
|
|
4791
|
+
|
|
4792
|
+
let operation = parseOp(`
|
|
4793
|
+
{
|
|
4794
|
+
ts {
|
|
4795
|
+
v
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
`, schema);
|
|
4799
|
+
|
|
4800
|
+
let queryPlan = buildPlan(operation, queryPlanner);
|
|
4801
|
+
const expectedPlan = `
|
|
4802
|
+
QueryPlan {
|
|
4803
|
+
Sequence {
|
|
4804
|
+
Fetch(service: "s1") {
|
|
4805
|
+
{
|
|
4806
|
+
ts {
|
|
4807
|
+
__typename
|
|
4808
|
+
id
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4811
|
+
},
|
|
4812
|
+
Flatten(path: "ts.@") {
|
|
4813
|
+
Fetch(service: "s2") {
|
|
4814
|
+
{
|
|
4815
|
+
... on I {
|
|
4816
|
+
__typename
|
|
4817
|
+
id
|
|
4818
|
+
}
|
|
4819
|
+
} =>
|
|
4820
|
+
{
|
|
4821
|
+
... on I {
|
|
4822
|
+
__typename
|
|
4823
|
+
required
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
},
|
|
4827
|
+
},
|
|
4828
|
+
Flatten(path: "ts.@") {
|
|
4829
|
+
Fetch(service: "s3") {
|
|
4830
|
+
{
|
|
4831
|
+
... on I {
|
|
4832
|
+
__typename
|
|
4833
|
+
required
|
|
4834
|
+
id
|
|
4835
|
+
}
|
|
4836
|
+
} =>
|
|
4837
|
+
{
|
|
4838
|
+
... on I {
|
|
4839
|
+
v
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
},
|
|
4843
|
+
},
|
|
4844
|
+
},
|
|
4845
|
+
}
|
|
4846
|
+
`;
|
|
4847
|
+
expect(queryPlan).toMatchInlineSnapshot(expectedPlan);
|
|
4848
|
+
|
|
4849
|
+
let response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
4850
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
4851
|
+
Object {
|
|
4852
|
+
"ts": Array [
|
|
4853
|
+
Object {
|
|
4854
|
+
"v": "req=r2",
|
|
4855
|
+
},
|
|
4856
|
+
Object {
|
|
4857
|
+
"v": "req=r4",
|
|
4858
|
+
},
|
|
4859
|
+
Object {
|
|
4860
|
+
"v": "req=r1",
|
|
4861
|
+
},
|
|
4862
|
+
],
|
|
4863
|
+
}
|
|
4864
|
+
`);
|
|
4865
|
+
});
|
|
4602
4866
|
});
|
|
4603
4867
|
|
|
4604
4868
|
describe('fields with conflicting types needing aliasing', () => {
|
|
@@ -88,7 +88,7 @@ it('correctly passes the context from ApolloServer to datasources', async () =>
|
|
|
88
88
|
.reply(
|
|
89
89
|
200,
|
|
90
90
|
{
|
|
91
|
-
data: { me: { username: '@
|
|
91
|
+
data: { me: { username: '@apollo-user' } },
|
|
92
92
|
},
|
|
93
93
|
replyHeaders,
|
|
94
94
|
);
|
|
@@ -107,7 +107,7 @@ it('correctly passes the context from ApolloServer to datasources', async () =>
|
|
|
107
107
|
const { data, errors } = unwrapSingleResultKind(result);
|
|
108
108
|
expect(errors).toBeUndefined();
|
|
109
109
|
expect(data).toEqual({
|
|
110
|
-
me: { username: '@
|
|
110
|
+
me: { username: '@apollo-user' },
|
|
111
111
|
});
|
|
112
112
|
});
|
|
113
113
|
|
|
@@ -62,7 +62,7 @@ describe('Using supergraphSdl static configuration', () => {
|
|
|
62
62
|
|
|
63
63
|
nock(accounts.url)
|
|
64
64
|
.post('/', { query: '{me{username}}', variables: {} })
|
|
65
|
-
.reply(200, { data: { me: { username: '@
|
|
65
|
+
.reply(200, { data: { me: { username: '@apollo-user' } } });
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
const result = await server.executeOperation({
|
|
@@ -72,7 +72,7 @@ describe('Using supergraphSdl static configuration', () => {
|
|
|
72
72
|
expect(unwrapSingleResultKind(result).data).toMatchInlineSnapshot(`
|
|
73
73
|
Object {
|
|
74
74
|
"me": Object {
|
|
75
|
-
"username": "@
|
|
75
|
+
"username": "@apollo-user",
|
|
76
76
|
},
|
|
77
77
|
}
|
|
78
78
|
`);
|
|
@@ -6,8 +6,8 @@ expect.addSnapshotSerializer(astSerializer);
|
|
|
6
6
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
7
7
|
|
|
8
8
|
const users = [
|
|
9
|
-
{ id: '1', name: 'Trevor
|
|
10
|
-
{ id: '1', name: 'Trevor
|
|
9
|
+
{ id: '1', name: 'Trevor', organizationId: '1', __typename: 'User' },
|
|
10
|
+
{ id: '1', name: 'Trevor', organizationId: '2', __typename: 'User' },
|
|
11
11
|
{ id: '2', name: 'James Baxley', organizationId: '1', __typename: 'User' },
|
|
12
12
|
{ id: '2', name: 'James Baxley', organizationId: '3', __typename: 'User' },
|
|
13
13
|
];
|
|
@@ -162,7 +162,7 @@ it('works fetches data correctly with complex / nested @key fields', async () =>
|
|
|
162
162
|
reviews: [
|
|
163
163
|
{
|
|
164
164
|
author: {
|
|
165
|
-
name: 'Trevor
|
|
165
|
+
name: 'Trevor',
|
|
166
166
|
organization: {
|
|
167
167
|
name: 'Apollo',
|
|
168
168
|
},
|
|
@@ -170,7 +170,7 @@ it('works fetches data correctly with complex / nested @key fields', async () =>
|
|
|
170
170
|
},
|
|
171
171
|
{
|
|
172
172
|
author: {
|
|
173
|
-
name: 'Trevor
|
|
173
|
+
name: 'Trevor',
|
|
174
174
|
organization: {
|
|
175
175
|
name: 'Wayfair',
|
|
176
176
|
},
|
|
@@ -6,7 +6,7 @@ expect.addSnapshotSerializer(astSerializer);
|
|
|
6
6
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
7
7
|
|
|
8
8
|
const users = [
|
|
9
|
-
{ id: ['1', '1'], name: 'Trevor
|
|
9
|
+
{ id: ['1', '1'], name: 'Trevor', __typename: 'User' },
|
|
10
10
|
{ id: ['2', '2'], name: 'James Baxley', __typename: 'User' },
|
|
11
11
|
];
|
|
12
12
|
|
|
@@ -89,7 +89,7 @@ it('fetches data correctly list type @key fields', async () => {
|
|
|
89
89
|
|
|
90
90
|
expect(data).toEqual({
|
|
91
91
|
reviews: [
|
|
92
|
-
{ body: 'Good', author: { name: 'Trevor
|
|
92
|
+
{ body: 'Good', author: { name: 'Trevor' } },
|
|
93
93
|
{ body: 'Bad', author: { name: 'James Baxley' } },
|
|
94
94
|
],
|
|
95
95
|
});
|
|
@@ -7,7 +7,7 @@ expect.addSnapshotSerializer(queryPlanSerializer);
|
|
|
7
7
|
|
|
8
8
|
const users = [
|
|
9
9
|
{ ssn: '111-11-1111', name: 'Trevor', id: '10', __typename: 'User' },
|
|
10
|
-
{ ssn: '222-22-2222', name: '
|
|
10
|
+
{ ssn: '222-22-2222', name: 'Joel', id: '20', __typename: 'User' },
|
|
11
11
|
{ ssn: '333-33-3333', name: 'James', id: '30', __typename: 'User' },
|
|
12
12
|
{ ssn: '444-44-4444', name: 'Baxley', id: '40', __typename: 'User' },
|
|
13
13
|
];
|
|
@@ -148,7 +148,7 @@ it('fetches data correctly with multiple @key fields', async () => {
|
|
|
148
148
|
body: 'B',
|
|
149
149
|
author: {
|
|
150
150
|
risk: 0.2,
|
|
151
|
-
name: '
|
|
151
|
+
name: 'Joel',
|
|
152
152
|
},
|
|
153
153
|
},
|
|
154
154
|
{
|
|
@@ -98,14 +98,7 @@ describe('value types', () => {
|
|
|
98
98
|
reviews {
|
|
99
99
|
metadata {
|
|
100
100
|
__typename
|
|
101
|
-
...
|
|
102
|
-
key
|
|
103
|
-
value
|
|
104
|
-
}
|
|
105
|
-
... on Error {
|
|
106
|
-
code
|
|
107
|
-
message
|
|
108
|
-
}
|
|
101
|
+
...Metadata
|
|
109
102
|
}
|
|
110
103
|
}
|
|
111
104
|
}
|
|
@@ -113,18 +106,22 @@ describe('value types', () => {
|
|
|
113
106
|
reviews {
|
|
114
107
|
metadata {
|
|
115
108
|
__typename
|
|
116
|
-
...
|
|
117
|
-
key
|
|
118
|
-
value
|
|
119
|
-
}
|
|
120
|
-
... on Error {
|
|
121
|
-
code
|
|
122
|
-
message
|
|
123
|
-
}
|
|
109
|
+
...Metadata
|
|
124
110
|
}
|
|
125
111
|
}
|
|
126
112
|
}
|
|
127
113
|
}
|
|
114
|
+
|
|
115
|
+
fragment Metadata on MetadataOrError {
|
|
116
|
+
... on KeyValue {
|
|
117
|
+
key
|
|
118
|
+
value
|
|
119
|
+
}
|
|
120
|
+
... on Error {
|
|
121
|
+
code
|
|
122
|
+
message
|
|
123
|
+
}
|
|
124
|
+
}
|
|
128
125
|
},
|
|
129
126
|
},
|
|
130
127
|
Flatten(path: "topProducts.@") {
|