Closed aliwoodman closed 3 years ago
We've got this working now. We needed to tell the Apollo Client about the possible return types, via something called an IntrospectionFragmentMatcher - something not currently mentioned in the AWS docs we were following.
In case anyone else finds it useful, this is roughly how we now set it up and pass it into our AWSAppSyncClient
configuration:
const introspectionQueryResultData = {
"__schema": {
"types": [
{
"kind": "INTERFACE",
"name": "UserResponse",
"possibleTypes": [{ "name": "User" }, { "name": "Error" }]
}
]
}
}
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
});
const cache = new InMemoryCache({
fragmentMatcher,
});
const client = new AWSAppSyncClient(
{
url: APPSYNC_API_URL,
region: REGION,
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials,
},
disableOffline: true,
},
{
defaultOptions: {
query: {
fetchPolicy: 'network-only',
},
},
cache,
}
);
> We've got this working now. We needed to tell the Apollo Client about the possible return types, via something called an [IntrospectionFragmentMatcher](https://www.apollographql.com/docs/react/data/fragments/#using-fragments-with-unions-and-interfaces) - something not currently mentioned in the [AWS docs](https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-node.html) we were following.
>
> In case anyone else finds it useful, this is roughly how we now set it up and pass it into our `AWSAppSyncClient` configuration:
Where can we import these classes? IntrospectionFragmentMatcher, InMemoryCache - trying this but it's not working:
import {InMemoryCache} from "aws-appsync/node_modules/apollo-cache-inmemory"
I added package apollo-cache-inmemory
to my app and this seems to be working in typescript. Note I had to cast the cache as "any", it was asking for ApolloCache<NormalizedCacheObject>
but not sure how/where to locate that, but this seems to work.
The creation of the fragmentTypes.json is taken from the schema.json pulled from my endpoint, more info here: https://www.apollographql.com/docs/react/v2/data/fragments/#fragments-on-unions-and-interfaces
current relevant package.json contents:
"devDependencies": {
"@types/aws-lambda": "^8.10.81",
"@types/aws-sdk": "^2.7.0",
"@types/lodash": "^4.14.175",
"@types/uuid": "^8.3.1",
"aws-sdk": "^2.1036.0",
"typescript": "^4.4.3"
},
"dependencies": {
"@types/node": "^16.9.6",
"apollo-cache-inmemory": "^1.6.6",
"autodetect-decoder-stream": "^2.0.0",
"aws-appsync": "^4.1.1",
"es6-promise": "^4.2.8",
"graphql": "^15.5.0",
"graphql-tag": "^2.11.0",
"http": "^0.0.1-security",
"isomorphic-fetch": "^3.0.0",
"lodash": "^4.17.21",
"mycompany-private-schema-package": "~1.0.0",
"uuid": "^8.3.2",
"ws": "^7.4.4"
}
import AWS from "aws-sdk";
import AWSAppSyncClient from "aws-appsync";
import { IntrospectionFragmentMatcher, InMemoryCache } from "apollo-cache-inmemory";
import introspectionQueryResultData from "mycompany-private-schema-package/dist/fragmentTypes.json";
const region = process.env.AWS_REGION;
const endpoint = process.env.GRAPHQL_ENDPOINT;
export default class getAppSyncClient {
constructor() {
console.log("getAppSyncClient() INIT");
}
public async parse() {
console.log("return AWSAppSyncClient()");
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
});
const cache: any = new InMemoryCache({
fragmentMatcher,
});
let client = new AWSAppSyncClient(
{
url: endpoint!,
region: region!,
auth: {
type: "AWS_IAM",
credentials: async () => {
let c = await new AWS.CredentialProviderChain().resolvePromise();
return c;
},
},
disableOffline: true,
},
{
defaultOptions: {
query: {
fetchPolicy: "network-only",
},
},
cache,
}
);
let the_client = await client.hydrated();
return the_client;
}
}
Thank you so much @slikk66 ; I've been trying all sorts of things to get this to work this afternoon. Stumbled upon this issue and saw your comment only 19 hours ago!
For the casting of the cache to any
; this is due to different versions of apollo-cache-inmemory
being used between aws-appsync
and yourself. Here are my versions (I just matched my version to use the same as aws-appsync
) that resolved the need for the cast:
"aws-appsync": "4.1.4",
"apollo-cache-inmemory": "1.3.12",
Do you want to request a feature or report a bug? Report a (possible) bug
What is the current behavior? A query for a union type results in the following response from AWSAppSyncClient: { data: null, loading: false, networkStatus: 7, stale: true }
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.
Our resolvers are implemented in AWS Lambda. We have set the
fetchPolicy
to 'network-only' anddisableOffline
to true when initialising the client.GraphQL schema:
Query:
Resolver:
If we know we are getting the 'User' response from the resolver and we remove the
...on Error
part of the query, we successfully get data back from the AppSync client. If we leave the query as above, we get null data even when our logs show that the resolver is returning one of the types in the union.What is the expected behavior?
We would expect this query to successfully return data without having to take this step. This works in the AppSync console but not when making the request from a lambda via apollo-client.
Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions?
node 12.16