I recently updated from 0.13.2 to 14.0.2 which includes breaking changes.
This introduced errors with existing queries which include MongoDB Object Ids (probably from #1382):
ID cannot represent value: { _bsontype: \"ObjectID\", id:
}
Repository with complete, minimal repeatable example here:
const Thing = mongoose.model('Thing', new mongoose.Schema({
id: mongoose.Schema.Types.ObjectId,
name: String
}));
const ThingType = new GraphQLObjectType({
name: 'thing',
fields: function () {
return {
id: { type: GraphQLID },
name: { type: GraphQLString }
}
}
});
const RootMutation = new GraphQLObjectType({
name: 'CreateMutation',
fields: {
create: {
type: ThingType,
description: 'Create new thing',
args: {
name: {
name: 'Name of Thing',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, args) => {
const newThing = new Thing({ name: args.name });
newThing.id = newThing._id;
return new Promise((res, rej) => {
newThing.save(err => {
if (err) return rej(err);
res(newThing);
});
});
}
}
}
});
Background: I'm a learner. Following this tutorial I encountered this problem which was _very_ confusing trying to debug. It would be nice if there was perhaps a clearer error message (*GraphQLID* cannot represent value... (instead of just ID) would have helped me a lot). Perhaps adding an indication of how to properly cast a MongoDB ObjectID?
@alexmcmillan Thanks for detail description and especially example repo 馃憤
It should be fixed by #1520
It would be nice if there was perhaps a clearer error message (GraphQLID cannot represent value... (instead of just ID) would have helped me a lot).
Problem is that you can define GraphQL types in SDL without working directly with GraphQL* classes:
type thing {
id: ID
name: String
}
So we can't use GraphQLID in error message because it will confuse SDL users.
Perhaps adding an indication of how to properly cast a MongoDB ObjectID?
We can't have mongoose as a dependency so we can't detect that some object is coming from Mongo.
@IvanGoncharov that makes perfect sense, thank you for your clear explanations here. Hope your solution gets merged soon so I can come forward to v14 :)
any changes this gets into 14.0.3?
Yes, I am still stuck using '^0.13.2' as the latest '^14.0.2' continues to give me these issues.
I would also like to know if it has been fixed for the ^14.0.2,
Why am I having to use the ^0.13.2
I tested the version ^14.0.2 and returned the same problem! :(
@RadAcademy @GlauberF We plan to include it into the next release.
However since instead of depending on toString we now using toJSON it can't be a patch release. So we are working on 14.1.0 that will include this and a few other features.
We will try to release RC ASAP.
I'm a newbie at apollo, me and my aspiration .... arggh. the JS fatigue is real. Wanted to let redux go, by only using this now. here's my very small project:
server:
const express = require("express");
const mongoose = require("mongoose");
require("dotenv").config({ path: "variables.env" }); //a juste besoin du path
//const bodyParser = require('body-parser');
const { ApolloServer, gql} = require('apollo-server-express');
const cors = require("cors"); // pour que react chiasse pas en faisant des calls
mongoose
.connect(process.env.MONGO_URI, { useNewUrlParser: true, useCreateIndex: true })
.then(() => console.log("Db connect茅"))
.catch(err => console.error(err));
const app = express();
//Schema
const Blog = require('./models/Blog');
const User = require('./models/User');
// //typedefs et resolvers
const { typeDefs } = require('./schema')
const { resolvers } = require('./resolvers')
//pour react
const corsOption = {
origin: "http://localhost:3000",
credentials: true
};
app.use(cors(corsOption));
const port = 4444;
const server = new ApolloServer({
typeDefs,
resolvers,
context: {
Blog,
User
}
});
server.applyMiddleware({app});
app.listen({ port }, () =>
console.log(`馃殌 Server ready at http://localhost:${port}${server.graphqlPath}`),
);
Blog shema
exports.typeDefs = `
type Blog {
_id: ID
title: String!
author: String
body: String!
date: String
}
type Query {
getAllBlogs: [Blog]
}
type Mutation {
addBlog(title: String!, author: String, body: String!) : Blog
}
`;
resolver:
exports.resolvers = {
Query: {
getAllBlogs: async(root, args, { Blog }) => await Blog.find().sort({
date: -1 //-1 = desc //1 = ascendant
})
},
Mutation: {
addBlog: async(root, { title, author, body }, { Blog }) => {
const newBlog = await new Blog({
title, author, body
}).save()
return newBlog
}
},
}
in react WHERE I GET Issues with ID:
import React from 'react';
import { Query } from "react-apollo";
import gql from "graphql-tag";
const GET_ALL_BLOGS = gql`
query {
getAllBlogs {
!!!!!IF I PUT _ID I GET THE ERROR !!!!!!!!!!!!!
title
author
body
date
}
}
`;
const App = props => {
return (
<div>
<h2>My first Apollo app </h2>
<Query query={GET_ALL_BLOGS}>
{({ data : { getAllBlogs } , loading, error }) => {
if (loading) return "Loading";
if (error) return `Error!: ${error}`;
return (
<ul>
{getAllBlogs.map(el => <li key={el.WOULDBE_ID}>{el.title}</li>)}
</ul>
);
}}
</Query>
</div>
);
};
index has the client, but it's ok, IT's that simple right now... Not sure what I'm doing wrong
@axe-z We already have a fix for this issue in #1520
We will try to release it ASAP.
oh thanks, when you are at your first steps like me , nosebleeds are ruff.
@alexmcmillan @sibelius @RadAcademy @GlauberF @axe-z I went ahead and merged #1520.
So now you can use our npm branch as a temporary solution until we figure out how to release 14.1.0:
https://github.com/graphql/graphql-js#want-to-ride-the-bleeding-edge
Your query needs to match the string type of string! not string
I had the same issue, i resolved this issue by writing this code in the types definition file of graphql
import mongoose from "mongoose";
const { ObjectId } = mongoose.Types;
ObjectId.prototype.valueOf = function() {
return this.toString();
};
should this be done on mongoose instead of graphql-js?
@vkarpov15 does it make sense to ObjectId implement valueOf?
@sibelius not a bad idea. Opened up a mongoose issue to track this
@vkarpov15 tks, keep the good work
still not fixed?
I don't use graphql so I'm not certain whether this is fixed, but this might help: http://thecodebarbarian.com/whats-new-in-mongoose-54-global-schematype-configuration.html
@infinitegachi try to use this mongoose PR https://github.com/Automattic/mongoose/pull/7353
I've made a field resolver to help on this
import { GraphQLNonNull, GraphQLString } from 'graphql';
import { Types } from 'mongoose';
export const mongooseIDResolver = {
_id: {
type: GraphQLNonNull(GraphQLString),
description: 'mongoose _id',
resolve: ({ _id }: { _id: Types.ObjectId}) => ({ _id: _id.toString() }),
},
};
so if you want to expose an _id in your GraphQL, you need a custom type or transform ObjectId to string
@sibelius just FYI, Mongoose does not support import { Types } from 'mongoose' in general. It should work, but we recommend always using import mongoose from 'mongoose' to be safe because of how mongoose is structured.
Types.ObjectId is for typechecking only I guess
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5344bfc805/types/mongoose/README.md#faq-and-common-mistakes
I believe this is fixed in ^14.2.1 and mongoose ^5.4.20
Most helpful comment
@alexmcmillan @sibelius @RadAcademy @GlauberF @axe-z I went ahead and merged #1520.
So now you can use our
npmbranch as a temporary solution until we figure out how to release14.1.0:https://github.com/graphql/graphql-js#want-to-ride-the-bleeding-edge