How to fix constructor error in GraphQL Mutation with Mongoose Schema [duplicate] - mongodb

This question already has answers here:
Mongoose TypeError: User is not a constructor
(1 answer)
TypeError: User is not a constructor
(6 answers)
Closed 3 years ago.
Having a lot of trouble with a GraphQL mutation Mongoose error for validating if a user is new or existing in MongoDB. Per the code below the error message is "message": "User is not a constructor".
A similar issue is here, and I redefined the variable below given each method in the solution to that linked issue with similar errors - only change in error was due to lacking constructor such as when I used other methods like append the error is "User is undefined".
CodeSandbox with all the code: https://codesandbox.io/s/apollo-server-sh19t?fontsize=14
The code in question is:
var userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
trim: true
},
password: {
type: String,
required: true,
trim: true
},
avatar: {
type: String
},
joinDate: {
type: Date,
default: Date.now
},
favorites: {
type: [mongoose.Schema.Types.ObjectId],
required: true,
ref: "Post"
}
});
// compile model
var User = mongoose.model("User", userSchema);
var getUserModel = function() {
return mongoose.model("User", userSchema);
};
Mutation: {
signupUser: async (_, { username, email, password }, { User }) => {
let user = await getUserModel().findOne({ username });
if (user) {
throw new Error("Please choose another username");
}
const newUser = await new User({
username,
email,
password
}).save();
return newUser;
}
}
};
The full error is:
{
"errors": [
{
"message": "User is not a constructor",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"signupUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: User is not a constructor",
" at signupUser (/xxx/xxx/xxx/servers.js:175:29)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
}
}
],
"data": null
}
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"signupUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'create' of undefined",
" at signupUser (/xxxx/xxxx/xxx/servers.js:175:38)"
Any assistance to this issue would be greatly appreciated.

That TypeError is thrown any time you try to use the new keyword with something that's not a constructing, including an undefined value. Even if you define a User variable outside of the constructor, you're still shadowing that variable because you're destructuring the context parameter and declaring a User variable that way. If you're not passing the User model to your context correctly, attempting to get the value from the context will result in the value being undefined. Either fix the context or don't unnecessarily destructure it.

Related

Mongoose Path "." is required - problem with PostmanMocking?

i am testing my mongoose (for MongoDB) schema, and I encountered an validation issue. After making POST verb I am getting en error:
"message": {
"errors": {
"number": {
"message": "Path `number` is required.",
"name": "ValidatorError",
"properties": {
"message": "Path `number` is required.",
"type": "required",
"path": "number"
},
"kind": "required",
"path": "number"
}
},
"_message": "eventArrayModel validation failed",
"message": "eventArrayModel validation failed: number: Path `number` is required.",
"name": "ValidationError"
}
This is my mocked json in Postman:
JSON mocked file
{
"arrayName": "displayedEvents",
"number": "4"
}
And this is my mongoose schema:
const mongoose = require("mongoose");
const eventSchema = new mongoose.Schema({
title: {
type: String,
// required: true,
},
start: {
type: Date,
// required: true,
},
end: {
type: Date,
// required: true,
},
allDay: {type: Boolean, default: true},
resource: {
type: String,
// required: true,
},
});
const eventArrayModel = mongoose.model("eventArrayModel", {
arrayName: {
type: String,
required: true,
},
array: {type: [eventSchema]} ,
number: {
type: Number,
required: true,
}
});
module.exports = eventArrayModel;
And the get router:
router.get('/', async (req,res)=> {
try{
const posts = await eventArrayModel.find();
res.json(posts);
}catch(err){
res.json({message: err});
}
});
I can't see anything wrong about this code. It works fine without number field.
Okey I found it, this part of code
router.post('/', async(req,res)=>{
const post = new eventArrayModel({
arrayName: req.body.arrayName
});
try {
const savedPost = await post.save();
res.json(savedPost);
}catch(err){
res.json({message: err});
}
});
Should looks more like this:
router.post('/', async(req,res)=>{
const post = new eventArrayModel({
arrayName: req.body.arrayName,
array: req.body.array,
myNumber: req.body.myNumber
});
try {
const savedPost = await post.save();
res.json(savedPost);
}catch(err){
res.json({message: err});
}
});

How to solve performing update on immutable fields in mongodb

I am writing a mutation to update a collection in the database
updateDiscoverUsers(_id:ID!,input: UpdateDiscoverUsersInput!): DiscoverUsers
The resolver function below is the one that handles that mutation
updateDiscoverUsers: async (args) => {
const auth = new DiscoverUsers({
geohash: args.input.geohash,
offenses: args.input.offenses,
online: args.input.online,
paid: args.input.paid,
profilePic: args.input.profilePic,
username: args.input.username,
creator: "5dab348c8890af1b8c25b22e"
})
const value = await DiscoverUsers.findByIdAndUpdate(args._id, { $set: auth }, { useFindAndModify: false, new: true })
if (!value) {
throw new Error('User doesnt exist')
}
return transformUser(value)
}
Then below is the type for the value to be returned
type DiscoverUsers{
_id:ID!
geohash: String!
offenses:Int
online: Int
paid: Boolean
profilePic: String
username: String
creator: Auth!
}
and also below is the input type that holds the value that would be used to update any field in the collection
input UpdateDiscoverUsersInput{
geohash: String
offenses:Int
online: Int
paid: Boolean
profilePic: String
username: String
}
But when I try to run the mutation in graphiql as shown below
mutation {
updateDiscoverUsers(_id:"5dab7c198a83f235c89a964a",input: {geohash:"dudknudnud", username: "Wacha"}){
username
}
}
I get an error that is displayed in my graphiql
{
"errors": [
{
"message": "Performing an update on the path '_id' would modify the immutable field '_id'",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateDiscoverUsers"
]
}
],
"data": {
"updateDiscoverUsers": null
}
}
I have tried to check where the problem seems to be, have check online and there wasn't a similar problem as this. Any help would be welcome and thank you in advance
Please use following code
const auth = {
geohash: args.input.geohash,
offenses: args.input.offenses,
online: args.input.online,
paid: args.input.paid,
profilePic: args.input.profilePic,
username: args.input.username,
creator: "5dab348c8890af1b8c25b22e"
};
const updateCond={_id:mongoose.Types.ObjectId(args._id)}
const value = await DiscoverUsers.findOneAndUpdate(updateCond, auth, { new: true });

GraphQLError Schema validation while triggering a mutation

I am trying my hand at GraphQL and I seem to have run into a strange error.
Here is my mutation
const createNewTask = {
name: "AddATask",
description: "A mutation using which you can add a task to the todo list",
type: taskType,
args: {
taskName: {
type: new gql.GraphQLNonNull(gql.GraphQLString)
},
authorId: {
type: new gql.GraphQLNonNull(gql.GraphQLString)
}
},
async resolve(_, params) {
try {
const task = newTask(params.taskName);
return await task.save();
} catch (err) {
throw new Error(err);
}
}
};
Task type is as defined as follows
const taskType = new gql.GraphQLObjectType({
name: "task",
description: "GraphQL type for the Task object",
fields: () => {
return {
id: {
type: gql.GraphQLNonNull(gql.GraphQLID)
},
taskName: {
type: gql.GraphQLNonNull(gql.GraphQLString)
},
taskDone: {
type: gql.GraphQLNonNull(gql.GraphQLBoolean)
},
authorId: {
type: gql.GraphQLNonNull(gql.GraphQLString)
}
}
}
});
I am trying to add a task using the graphiql playground.
mutation {
addTask(taskName: "Get something", authorId: "5cb8c2371ada735a84ec8403") {
id
taskName
taskDone
authorId
}
}
When I make this query I get the following error
"ValidationError: authorId: Path `authorId` is required."
But when I remove the authorId field from the mutation code and send over a mutation without the authorId in it, I get this error
"Unknown argument \"authorId\" on field \"addTask\" of type \"Mutation\"."
So this proves that the authorId is available is in the request. I debugged the same on vscode and can see the value. I can't seem to figure out what is wrong.
I figured out what the error was. The erro was actually caused by my mongoose schema and not by graphql schema.
const taskSchema = new Schema(
{
taskName: {
type: String,
required: true
},
taskDone: {
type: Boolean,
required: true
},
authorId: {
type: mongoose.Types.ObjectId,
required: true
}
},
{
collection: "tasks"
}
);
But what is wierd is that the final error message has no indication that it was the mongoose schema validation failure. And the error states that it is a graphql error hence the confusion. Hope it helps someone.

MongoDB validation allowing everything

I'm starting to use MongoDB node driver and I can't get validation to work at all.
I created the following validation objects using query:
validator: { $in: [
{ name: { $type: "string" } }
]}
And this JSON Schema:
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name"],
properties: {
name: {
bsonType: "string",
description: "is required and must be a string"
}
}
}
}
Then if I try to insert the following document with this structure {name: 2}, it gets added no failed validation whatsoever.
I've read the mongo and the node driver docs up and down regarding document validation and can't find a way to get this validated. I'm currently using Mongo version 3.6.7 and the node driver version 3.1.4, on an express server version 4.16.3.
This is the whole code:
// create a single user
const createSingleUser = (client, db) => {
db.collection("users").insertOne({
name: 2
}, (err, response) => {
if (err) console.warn(err);
console.log("new user added!!!!");
client.close();
}); // insert one
};
// create collection and add validator
const createUserCollection = client => {
const MongoDriverData = client.db("MongoDriverData");
// create the collection and add validation
MongoDriverData.createCollection( "users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name"],
properties: {
name: {
bsonType: "string",
description: "is required and must be a string"
}
}
}
}, // validator
validationAction: "error"
}, (err, results) => {
console.log( "Collection created!!!" );
// now insert a user
createSingleUser(client, MongoDriverData);
});
};

Ember.js - Error while loading route: TypeError: Cannot set property 'store' of undefined

I'm getting the following error in my Ember.js app.
Error while processing route: books Cannot set property 'store' of undefined TypeError: Cannot set property 'store' of undefined
at DS.Store.Ember.Object.extend.modelFor (http://localhost:8080/js/libs/ember-data.js:2986:19)
at DS.Store.Ember.Object.extend.recordForId (http://localhost:8080/js/libs/ember-data.js:2437:17)
at deserializeRecordId (http://localhost:8080/js/libs/ember-data.js:3355:23)
at deserializeRecordIds (http://localhost:8080/js/libs/ember-data.js:3369:5)
at http://localhost:8080/js/libs/ember-data.js:3335:7
at http://localhost:8080/js/libs/ember-data.js:7117:16
at http://localhost:8080/js/libs/ember.js:14899:20
at Object.OrderedSet.forEach (http://localhost:8080/js/libs/ember.js:14741:14)
at Object.Map.forEach (http://localhost:8080/js/libs/ember.js:14897:14)
at Function.DS.Model.reopenClass.eachRelationship (http://localhost:8080/js/libs/ember-data.js:7116:38)
I'm using
ember.js version 1.7.1 and
ember-data.js version 1.0.0-beta.5.
I have the following project:
window.App = Ember.Application.create();
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:8080'
});
App.Router.map(function() {
this.resource('books', { path: '/' });
});
App.BooksRoute = Ember.Route.extend({
model: function() {
return this.store.find('book');
}
});
App.Author = DS.Model.extend({
firstname: DS.attr('string'),
lastname: DS.attr('string')
});
App.Book = DS.Model.extend({
title: DS.attr('string'),
authors: DS.hasMany('author')
});
and the following is my JSON response to http://localhost:8080/books.
{
"books":
[
{
"id": 0,
"authors":
[
{
"id": 0,
"firstname": "Andrzej",
"lastname": "Sapkowski"
}
],
"title": "Zaklínač I: Poslední přání"
},
...
]
}
When I remove the Author model and the authors relationship declaration, the application works fine.
The error message I'm getting doesn't reveal the cause and according to what I've found on the Internet, my code seems to be ok.
What's the problem?
Wow, I can't believe I didn't notice this, but your data isn't formatted properly. It should look something like this:
{
"books": [{}, {}, {}],
"authors": [{}, {}, {}]
}
This is explained in the REST adapter guide.