I'm trying to disable cache on Apollo, therefore I'm following the documentation apollo-client
, but I cannot success, I get all the time this warning ApolloBoost was initialized with unsupported options: defaultOptions
Does anyone have the same warning ?
import Vue from 'vue'
import ApolloClient from 'apollo-boost'
const defaultOptions = {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore'
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all'
}
}
const client = new ApolloClient({
defaultOptions: defaultOptions,
)};
It looks like it's because you are using Apollo Boost, a wrapper around Apollo Client with slightly different API.
Try changing your import from:
import ApolloClient from "apollo-boost";
to:
import ApolloClient from "apollo-client";
or in v3:
import { ApolloClient } from '#apollo/client';
The "apollo-client" is more low level and harder to use. That's probably why the team created "apollo-boost".
But looking at the source code "apollo-boost" is a good way to understand how to use the low-level "apollo-client". For example:
import ApolloClient from 'apollo-client';
import { FetchResult } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
// in v3, the types moved:
// import { ApolloClient } from '#apollo/client';
const apolloClient = new ApolloClient({
link: new HttpLink({
uri: '/graphql',
credentials: 'same-origin',
}),
cache: new InMemoryCache(),
defaultOptions: {
query: {
errorPolicy: 'all',
},
},
});
See also the docs on migration from Apollo Boost to Apollo Client like Intellidroid said.
Related
I'm trying to write the e2e test for my backend app (nestjs, grpahql, mongodb).
This is my test:
import { INestApplication } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { Test, TestingModule } from '#nestjs/testing';
import {
ApolloServerTestClient,
createTestClient,
} from 'apollo-server-testing';
import gql from 'graphql-tag';
import { UserModule } from '../src/user/user.module';
import { MongooseModule } from '#nestjs/mongoose';
import config from '../src/environments/environment';
describe('User', () => {
let app: INestApplication;
let apolloClient: ApolloServerTestClient;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [UserModule, MongooseModule.forRoot(config.mongoURI)],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
const module: GraphQLModule = moduleFixture.get<GraphQLModule>(
GraphQLModule,
);
apolloClient = createTestClient((module as any).apolloServer);
});
it('should get users', async () => {
const { query } = apolloClient;
const result: any = await query({
query: gql`
query {
getUsers {
_id
name
}
}
`,
variables: {},
});
console.log(result);
});
});
I face this error:
Nest could not find GraphQLModule element (this provider does not exist in the current context)
Could someone share a working example or point me what is wrong?
It looks like GraphQLModule is not imported in the scope of your TestModule. If so, the context will never be able to provide it using get().
Also, this might not help you but this is what we do in our projects:
beforeAll(async () => {
const TCP_PORT = 4242;
const testingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
gqlClient = new ApolloClient({
uri: `http://localhost:${TCP_PORT}/graphql`,
fetch: fetch as any,
cache: new InMemoryCache({
addTypename: false,
}),
});
app = testingModule.createNestApplication();
await app.listen(TCP_PORT);
});
I did not add all the imports but here are the most relevant:
import ApolloClient, { gql, InMemoryCache } from 'apollo-boost';
import fetch from 'node-fetch';
I assume you know the other ones and/or don't need them
I've been having issues getting started with React, Apollo, and AWS-AppSync. I can't resolve this error message:
TypeError: this.currentObservable.query.getCurrentResult is not a function
I'm using the updated packages of #apollo/react-hooks and aws-appsync.
My current setup looks like this.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import config from './aws-exports';
import AWSAppSyncClient from 'aws-appsync';
import { ApolloProvider } from '#apollo/react-hooks';
const client = new AWSAppSyncClient({
url: config.aws_appsync_graphqlEndpoint,
region: config.aws_appsync_region,
auth: {
type: config.aws_appsync_authenticationType,
apiKey: config.aws_appsync_apiKey
}
});
ReactDOM.render(
<ApolloProvider client={client}>
<React.StrictMode>
<App />
</React.StrictMode>
</ApolloProvider>,
document.getElementById('root')
);
And I have a function that makes a query that looks like this:
import React from 'react';
import { useQuery } from '#apollo/react-hooks';
import gql from 'graphql-tag';
const Flavors = () => {
const GET_FLAVORS = gql`
query listAll {
items {
name,
image
}
}
`;
const { loading, error, data } = useQuery(GET_FLAVORS);
if(loading) return <p>loading...</p>
if(error) return <p>Something went wrong...</p>
return (
<div>
{
data.listIceCreamTypes.items.map(type => {
return <div key={type.name}>
<img src={type.image} alt={type.name} />
<h1>{type.name}</h1>
</div>
})
}
</div>
)
}
export default Flavors;
I've gone through various solutions described in https://github.com/apollographql/react-apollo/issues/3148 such as adding:
"resolutions": {
"apollo-client": "2.6.3"
}
to package.json. Then re-running npm install and restarting the server.
Nothing seems to solve my issues.
Edit** Here's a repo to reproduce the problem: https://github.com/Rynebenson/IceCreamQL
I already answered this on other related question here on stackoverflow..
As mentioned in other answer the problem is because aws-appsync is relying in an previous version apollo-client. Using resolutions is not the "cleaner" way to solve this problem as you're fixing a dependency version which is not fully compatible with this library.
I strongly recommend you to create a custom apollo client for AWS AppSync this way:
import { ApolloProvider } from '#apollo/react-hooks';
import { ApolloLink } from 'apollo-link';
import { createAuthLink } from 'aws-appsync-auth-link';
import { createHttpLink } from 'apollo-link-http';
import { AppSyncConfig } from './aws-exports';
import ApolloClient from 'apollo-client';
const url = AppSyncConfig.graphqlEndpoint;
const region = AppSyncConfig.region;
const auth = {
type: AppSyncConfig.authenticationType,
apiKey: AppSyncConfig.apiKey
};
const link = ApolloLink.from([
createAuthLink({ url, region, auth }),
createHttpLink({ uri: url })
]);
const client = new ApolloClient({
link,
cache: new InMemoryCache()
});
const WithProvider = () => (
<ApolloProvider client={client}>
<App />
</ApolloProvider>
)
export default WithProvider
I also created a more detailed post on medium
Wanted to post my experience that is a more recent. The accepted answer is still correct. aws-appsync uses outdated packages which conflict with the newest versions of the apollo client.
import React from 'react';
import PropTypes from 'prop-types';
// Apollo Settings
import { ApolloClient, ApolloProvider, InMemoryCache } from '#apollo/client';
import { ApolloLink } from 'apollo-link';
// AppSync
import { Auth } from 'aws-amplify';
import { createAuthLink } from 'aws-appsync-auth-link';
import { createHttpLink } from 'apollo-link-http';
import awsconfig from 'assets/lib/aws-exports';
// jwtToken is used for AWS Cognito.
const client = new ApolloClient({
link: ApolloLink.from([
createAuthLink({
url: awsconfig.aws_appsync_graphqlEndpoint,
region: awsconfig.aws_appsync_region,
auth: {
type: awsconfig.aws_appsync_authenticationType,
apiKey: awsconfig.aws_appsync_apiKey,
jwtToken: async () => (await Auth.currentSession()).getAccessToken().getJwtToken(),
},
}),
createHttpLink({ uri: awsconfig.aws_appsync_graphqlEndpoint }),
]),
cache: new InMemoryCache(),
});
const withApollo = ({ children}) => {
return <ApolloProvider client={client}><App /></ApolloProvider>;
};
withApollo.propTypes = {
children: PropTypes.object,
authData: PropTypes.object,
};
export default withApollo;
Package.json
"#apollo/client": "^3.3.15",
"#apollo/react-hooks": "^4.0.0",
"apollo-link": "^1.2.14",
"apollo-link-http": "^1.5.17",
"aws-amplify": "^3.3.27",
"aws-amplify-react-native": "^4.3.2",
"aws-appsync-auth-link": "^3.0.4",
You must initialize appsync like the following method.
const graphqlClient = new appsync.AWSAppSyncClient({
url: graphqlEndpoint,
region: process.env.AWS_REGION,
auth: {
type: 'AWS_IAM',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
sessionToken: process.env.AWS_SESSION_TOKEN
}
},
disableOffline: true
});
below is my setup of Gatsby SSR with Apollo for those looking for a solution on how to set them up. Hope it helps those looking online for a solution on how to set up Gatsby with Apollo
Credits: [https://github.com/apollographql/subscriptions-transport-ws/issues/333]
I am not sure at the moment if my onError variable is placed correctly. I will look it up
Nonetheless, subscription with gatsby client-side routes is working fine with this setup
client.js // to be imported into ApolloProvider
import ApolloClient from 'apollo-client'
// import * as ws from 'ws'
// import { createHttpLink } from 'apollo-link-http'
import { split } from 'apollo-link'
// import { setContext } from 'apollo-link-context'
import { onError } from 'apollo-link-error'
import { HttpLink } from 'apollo-link-http'
import { WebSocketLink } from 'apollo-link-ws'
// import fetch from 'isomorphic-fetch' // Comment out this line results in an error ...
import 'isomorphic-fetch'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { getMainDefinition } from 'apollo-utilities'
const HTTP_URI = `http://localhost:4000/graphql`
const WS_URI = `ws://localhost:4000/graphql`
const httplink = new HttpLink({
uri: HTTP_URI,
// credentials: 'same-origin',
// fetch,
})
const wsLink = process.browser
? new WebSocketLink({
// if you instantiate in the server, the error will be thrown
uri: WS_URI,
options: {
reconnect: true,
},
})
: null
const errorLink = onError(({ networkError, graphQLErrors }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
})
const link = process.browser
? split(
//only create the split in the browser
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
httplink,
errorLink
)
: httplink
export const client = new ApolloClient({
link,
cache: new InMemoryCache(),
})
graphql/subscriptions.js
import gql from 'graphql-tag'
const BOOK_ADDED_SUBSCRIPTION = gql`
subscription {
bookAdded {
_id
title
author
}
}
`
export { BOOK_ADDED_SUBSCRIPTION }
To do graphql queries and mutations ive had success with both fetch and svelte-apollo (see https://github.com/timhall/svelte-apollo)
I like the fech approach for its simplicity.
Svelte-apollo features subscriptions and I will try to get it to work.
But are there alternatives?
How do you consume graphql subscriptions with svelte?
Heres my solution, using Apollo:
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
const httpLink = new HttpLink({
uri: 'http://localhost:3000/graphql'
});
const wsLink = new WebSocketLink({
uri: `ws://localhost:3000/subscriptions`,
options: {
reconnect: true
}
});
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
const client = new ApolloClient({
link,
cache: new InMemoryCache()
});
After all that, you have your client set up. Next,
import gql from 'graphql-tag';
client.subscribe({
query: gql`subscription { whatever }`
}).subscribe(result => console.log(result.data);
I'm using urql's svelte bindings. The documentation also shows how to use the bindings with subscriptions.
My Apollo queries and mutations are working perfectly. Now I'm adding a subscription and for some reason graphIql (please note the I in graphIql) can't trigger the subscription. A breakpoint in the subscription doesn't activate, and the data comes back to graphIql as null. There are no console log errors in graphIql.
Here's the relevant code:
TYPES
type Resolution {
_id: String!
name: String!
goals: [Goal]
completed: Boolean
}
type Query {
resolutions: [Resolution]
getResolutionViaId(resolutionId: String!): Resolution
}
type Mutation {
createResolution(name: String!): Resolution
}
type Subscription {
resolutionWasAdded: Resolution
}
RESOLVERS
Subscription: {
resolutionWasAdded: {
subscribe: () => pubsub.asyncIterator(RESOLUTION_SUBSCRIPTION_TOPIC)
}
}
QUERY ENTERED IN GRAPHIQL
subscription resolutionWasAdded {
resolutionWasAdded {
__typename
_id
name
completed
}
}
RESPONSE IN GRAPHIQL
{
"data": {
"resolutionWasAdded": null
}
}
What could I be missing?
UPDATE
I see I need to set up graphIql to be aware of my subscription endpoint. I've googled quite a bit but don't yet see how to do it with this client setup:
import React from "react";
import {Meteor} from "meteor/meteor";
import {render} from "react-dom";
import {ApolloProvider} from "react-apollo";
import {ApolloLink, from} from "apollo-link";
import {ApolloClient} from "apollo-client";
import {HttpLink} from "apollo-link-http";
import {InMemoryCache} from "apollo-cache-inmemory";
import {onError} from 'apollo-link-error';
import {split} from 'apollo-link';
import {WebSocketLink} from 'apollo-link-ws';
import {getMainDefinition} from 'apollo-utilities';
import {toIdValue} from 'apollo-utilities';
import App from "../../ui/App";
// Create an http link:
const httpLink = new HttpLink({
uri: Meteor.absoluteUrl("graphql"),
credentials: 'same-origin'
})
// Create a WebSocket link:
const wsLink = new WebSocketLink({
uri: `ws://localhost:3200/subscriptions`,
options: {
reconnect: true
}
});
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const splitLink = split(
// split based on operation type
({query}) => {
const {kind, operation} = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const authLink = new ApolloLink((operation, forward) => {
const token = Accounts._storedLoginToken();
operation.setContext(() => ({
headers: {
"meteor-login-token": token
}
}));
return forward(operation);
});
const client = new ApolloClient({
link: ApolloLink.from([
onError(({graphQLErrors, networkError}) => {
if (graphQLErrors)
graphQLErrors.map(({message, locations, path}) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.log(`[Network error]: ${networkError}`);
}),
authLink,
splitLink,
]),
cache: new InMemoryCache({})
});
const ApolloApp = () => (
<ApolloProvider client={client}>
<App/>
</ApolloProvider>
);
Meteor.startup(() => {
render(<ApolloApp/>, document.getElementById("app"));
});
What is the correct way to modify this setup so as to tell graphIql about the subscription endpoint?