Apollo Client Error | Type 'RestLink' is not assignable to type 'ApolloLink' - apollo-client

Now I am trying to use apolloClient with both graphql and rest api in typescript.
Therefore, I applied apollo-link-rest. But I got the error below.
./node_modules/apollo-link-rest/bundle.umd.js
Module not found: Can't resolve 'graphql-anywhere/lib/async' in 'D:\forked\syntegrate_app_client\node_modules\apollo-link-rest'
Type 'RestLink' is not assignable to type 'ApolloLink'.
Types of property 'split' are incompatible.
Type '(test: (op: import("d:/forked/syntegrate_app_client/node_modules/#apollo/client/link/core/types").Operation) => boolean, left: import("d:/forked/syntegrate_app_client/node_modules/#apollo/client/link/core/ApolloLink").ApolloLink | import("d:/forked/syntegrate_app_client/node_modules/#apollo/client/link/core/types")....' is not assignable to type '(test: (op: import("d:/forked/syntegrate_app_client/node_modules/apollo-link/lib/types").Operation) => boolean, left: import("d:/forked/syntegrate_app_client/node_modules/apollo-link/lib/link").ApolloLink | import("d:/forked/syntegrate_app_client/node_modules/apollo-link/lib/types").RequestHandler, right?: import("d...'.
Types of parameters 'test' and 'test' are incompatible.
Types of parameters 'op' and 'op' are incompatible.
Property 'toKey' is missing in type 'import("d:/forked/syntegrate_app_client/node_modules/#apollo/client/link/core/types").Operation' but required in type 'import("d:/forked/syntegrate_app_client/node_modules/apollo-link/lib/types").Operation'.ts(2322)
types.d.ts(24, 5): 'toKey' is declared here.
This is the code that I used.
const restLink = new RestLink({
uri: process.env.REST_API
});
const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = getCookie("token");
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
STKN: token ? `${token}` : "",
},
};
});
const client = new ApolloClient({
// link: errorLink.concat(restLink).concat(authLink).concat(link),
link: ApolloLink.from([errorLink, restLink, authLink, link]),
cache,
resolvers,
});
and this is my version of #apollo/client
"dependencies": {
"#apollo/client": "^3.0.0-beta.44",
"#apollo/link-context": "^2.0.0-beta.3",
"apollo-link": "^1.2.14",
"apollo-link-batch-http": "^1.2.13",
"apollo-link-http": "^1.5.16",
"apollo-link-rest": "^0.8.0-beta.0",

If you want to use apollo-link-rest you will have to use version 0.7.3 and use apollo-client 2.6.10, this fixed the problem for me
The 0.8.0-beta.0 has not been updated in some time, and it's unclear if this will be maintained to work properly with #apollo/client 3

Related

react-admin dataprovider specify a custom field as primary key - a field that is not named "id"

I'm using the hasura data provider in react-admin ra-data-hasura (but i'm sure its more or less the same thing of ra-data-graphql)
My entity has their primary keys that are named differently from id
Is it possible to set a field as primary that is not named id Eg: MyEntityId
Is it possible to specifiy it resource by resource (because each table could have its own name pattern) or globally
Alex,
You have that answer in the docs: https://marmelab.com/react-admin/FAQ.html#can-i-have-custom-identifiersprimary-keys-for-my-resources
you have to resolve this at the dataProvider level.
You have to implement your own dataProvider's methods that mapped your MyEntityId field to the id field required by react-admin.
For example (implementing getList method):
const myDataProvider = {
getList: (resource, params) => {
return fetch(API_URL)
.then(({ json }) => ({
data: json.map((record) => ({ id: record.MyEntityId, ...record })),
total: parseInt(json.total, 10),
})
);
}
//...
}
json.map(record => ({"id": record.userID, ...record})),
Yes, you can customize the cache IDs using the keyFields for each type in the typePolicies option of the InMemoryCache constructor:
const client = new ApolloClient({
...
cache: new InMemoryCache({
typePolicies: {
MyEntity1: {
keyFields: ["MyEntityId"],
},
MyEntity2: {
keyFields: ["MyEntityId"],
},
...
}
}),
...
})
buildHasuraProvider({ client });

React Admin / building Data Provider via 'ra-data-graphql' library - auto-injected `raFetchType` param is undefined

I'm trying to create a dataProvider via ra-data-graphql, as described in the library's README, and am successfully passing in the introspection response to the buildQuery method, but the raFetchType param in my buildQuery method is always undefined, and the query mapping that is supposed to happen fails. It appears as though the raFetchType should be populated automatically by the library, or maybe I'm (or the documentation) missing something.
Do I need to provide some extra option when injecting buildCustomQuery into buildGraphQLProvider?
What you were expecting:
raFetchType is defined (I'm assuming as one of 'GET_LIST', 'GET_ONE', etc.)
What happened instead:
the raFetchType param in buildQuery (called aorFetchType in the library's source code) is always undefined
Related code:
// App.tsx
const [dataProvider, setDataProvider] = useState<DataProvider>();
const cache = new InMemoryCache();
const link = createHttpLink({
uri: // my graphql API URL
});
const client = new ApolloClient({
cache: cache,
link: link,
});
useEffect(() => {
buildGraphQLProvider({
client: { client },
buildQuery: buildCustomQuery,
introspection: {
schema, // JSON previously fetched from my GraphQL API
operationNames: introspectionOperationNames, // function that maps the 'Country' resource to the correct query name for 'GET_LIST'
include: ['Country'], // just trying it out with a single Resource first
},
}).then((dataProvider: any) => {
setDataProvider(dataProvider);
})
}, []);
// this is called via `buildGraphQLProvider` on init
export const buildCustomQuery = (introspectionResults: any) => (raFetchType: any, resourceName: any, params: any) => {
// the introspectionResults contain the 4 properties listed here: https://github.com/marmelab/react-admin/tree/master/packages/ra-data-graphql#specify-your-queries-and-mutations
// including the 'Country' resource with the mapped query name
// however, `raFetchType` is undefined, and so no query can ever be returned.
// I get 'TypeError: Cannot read property 'parseResponse' of undefined' on ra-data-graphql/esm/index.js:113
const resource = introspectionResults.resources.find((r: IntrospectionResource) => r.type.name === resourceName);
switch (raFetchType) {
case 'GET_LIST':
return {
query: gql`query ${resource[raFetchType].name}($id: ID) {
data: ${resource[raFetchType].name}(id: $id) {
...
}
}
}`,
variables: params, // params = { id: ... }
parseResponse: (response: any) => response.data,
}
break;
// ... other types handled here
default:
return undefined;
}
}
Environment
React-admin version: 3.11.0
React version: 17.0.1
Browser: Chrome
Stack trace: Uncaught (in promise) TypeError: Cannot read property 'parseResponse' of undefined at raDataProvider (index.js:113)

Error when building typedefs TypeError: Cannot read property 'some' of undefined

I am getting the following error when building Typedefs in Apollo Server:
return typeDef.definitions.some(definition => definition.kind === language_1.Kind.DIRECTIVE_DEFINITION &&
^
TypeError: Cannot read property 'some' of undefined
I tried to follow some solutions from here https://github.com/apollographql/apollo-server/issues/2961 but still, I am getting the error.
This is how I am creating the schema:
fs.readdirSync(__dirname)
.filter(dir => { console.log('dir', dir); return dir.indexOf('.') < 0 })
.forEach((dir) => {
const tmp = require(path.join(__dirname, dir)).default;
resolvers = merge(resolvers, tmp.resolvers);
typeDefs.push(tmp.types);
});
const schema = new ApolloServer({
typeDefs,
resolvers,
playground: {
endpoint: '/graphql',
settings: {
'editor.theme': 'light'
}
}
});
type.js
const Book = gql`
type Book {
title: String!
author: String!
}
`;
export const types = () => [Book];
export const typeResolvers = {
};
mutation.js
const Mutation = gql`
extend type Mutation {
addBook(book: BookInput): Book
}
`;
export const mutationTypes = () => [Mutation];
export const mutationResolvers = {
Mutation: {
addBook: async (_, args, ctx) => {
return []
}
}
};
index.js
export default {
types: () => [types, queryTypes, inputTypes, mutationTypes],
resolvers: Object.assign(queryResolvers, mutationResolvers, typeResolvers),
};
Any suggestions? What could I be missing?
I just had the same issue for the past 2 hours. I realized the file were i was instantiating my apollo server was being executed before the typedefs was created.
Simple way to test for this is to make a console.log(types, queryTypes, inputTypes, mutationTypes) right before the execution of const schema = new ApolloServer({ ....
One of them is undefined. Thanks.
After spending some time making changes, I finally got a working solution.
I had to make sure that typeDefs was an array of GraphQL Documents and not a type of [Function: types]. To do that, I removed unnecessary function syntax.
For example:
I replaced this export const types = () => [Book]; with this export const types = Book;
I replaced this types: () => [types, queryTypes, inputTypes, mutationTypes] with types: [types, queryTypes, inputTypes, mutationTypes]
... and pretty much every where I had () =>
Finally, before instantiating ApolloServer, instead of pushing tmp.types to the array of types, I used concat to use all defined graphql types in the I had defined the current file 'plus' the graphql types imported in every directory
typeDefs = typeDefs.concat(tmp.types);

How to handle Apollo Graphql query error in Vue.JS?

I am using Vue.js with Vue-Apollo and trying to fetch shared member list using query. I am using the graphQL service in backend.
I am using apollo 'error' function to handle GraphQL error. When the request is made with invalid input, I can see the errors in the network tab, I can see the JSON for the custom errors messages. But I can't console the errors in 'error' function.
Here is the apollo query that is used to fetch shared member list -
apollo: {
sharedMembers: {
query: gql`
query item($uuid: ID) {
item(uuid: $uuid) {
...itemTemplate
members {
...member
permission
}
}
}
${ITEM_TEMPLATE}
${MEMBER}
`,
variables() {
return {
uuid: this.$route.params.uuid,
}
},
update(data) {
return data.item.members
},
error(error) {
console.log('errors', error)
}
},
},
The network response I got -
network_error
Using graphQLErrors
You could get the errors by looking in the error object for graphQLErrors:
error(error) {
console.log('errors', error.graphQLErrors)
}
or
error({ graphQlErrors }) {
console.log('errors', graphQLErrors)
}
Using apollo-error-link
You can use apollo-error-link to help solve your problem if the above doesn't work, docs here.
Here's an example from the docs and I added to it in the networkErrors section to show what you can do to edit the error message you see in your error block, or catch block if its a mutation.
import { onError } from "apollo-link-error";
const link = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) {
// Add something like this to set the error message to the one from the server response
networkError.message = networkError.result.errors[0].debugMessage
console.log(`[Network error]: ${networkError}`)
};
});
And then in your code:
error(error) {
console.log('error-message', error.message)
}
The console should then log your debugMessage from the server.
unfortunately i couldn't find out how i'd handle errors in such of graphql method call, but as an option you could provide onError method to ApolloClient constructor options. first argument is the error object. hopefully it may help. like so..
const apolloClient = new ApolloClient({
uri: 'http://localhost:4000',
onError(err) {
console.log(err)
},
})

Apollo server 2.0. Type "Upload" not found in document

How to replicate:
server.js
const { ApolloServer, makeExecutableSchema, gql } = require('apollo-server');
const typeDefs = gql`
type Mutation {
uploadAvatar(upload: Upload!): String!
}
`;
const resolvers = {
Mutation: {
uploadAvatar(root, args, context, info) {
return 'test';
}
}
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const server = new ApolloServer({
schema,
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
package.json
"dependencies": {
"apollo-server": "^2.0.0-rc.6",
"graphql": "^0.13.2"
}
On node server.js we get the following error:
Type "Upload" not found in document.
Given the latest version of apollo server, am I supposed to add anything else to the query? According to this tutorial and few other sources that I currently cannot recall, one does not need to do anything more than just write Upload and it should work fine. Am I missing anything?
There are a couple of ways I've fixed this, in the example on the apollo docs:
https://www.apollographql.com/docs/guides/file-uploads.html
you can see he doesn't use makeExecutableSchema but passed the resolvers and schema to the apollo server this stopped the error:
Type "Upload" not found in document.
If you want to use makeExecutableSchema then import the scalar
const typeDefs = gql`
scalar Upload
type Mutation {
uploadAvatar(upload: Upload!): String!
}
type Query {
ping: String
}
`;
https://github.com/jaydenseric/apollo-upload-examples/blob/master/api/schema.mjs
if you look at some of the example source code for the at blog post you can see he uses a scalar
The reason it wasn't being added automatically is
Scalar Upload
The Upload type automatically added to the schema by Apollo Server resolves an object containing the following:
stream
filename
mimetype
encoding
UPDATE: Apollo have made it clearer that when you use makeExecutableSchema you need to define the scalar for it to work
In a situation where a schema is set manually using makeExecutableSchema and passed to the ApolloServer constructor using the schema params, add the Upload scalar to the type definitions and Upload to the resolver
https://www.apollographql.com/docs/guides/file-uploads.html#File-upload-with-schema-param

Resources