Apollo Graphql Event validation failed - mongodb

I have a mutation with input type but the response is Event validation failed, if try with the same mutation but with each argument input the mongoose validation is right.
This is with apollo 2 .
//Mutation fine
Mutation: {
createEvent: combineResolvers(
isAuthenticated,
async (parent, { text, description }, { models, me }) => {
const event = await models.Event.create({
text,description,
userId: me.id,
});
pubsub.publish(EVENTS.EVENT.CREATED, {
eventCreated: { event },
});
return event;
},
),
//Mutation with errors
createEventInput: combineResolvers(
isAuthenticated,
async (root, { input }, { models, me }) => {
const event = await models.Event.create(input,{
userId: me.id,
});
pubsub.publish(EVENTS.EVENT.CREATED, {
eventCreated: { event },
});
return event;
},
),
Error :
"errors": [ { "message": "Event validation failed: description: Path description is required., text: Path text is required.", "locations":

Related

PrismaClientValidationError: Missing required argument in connectOrCreate

Problem:When I try and send/store data in my database I get this error. Specifically, I am trying to create/save a classroom with student names.
Tech Used:
Prisma/Postgres connected to AWS RDS and Next.js, deployed on Vercel, etc.
Error Message
PrismaClientValidationError: Argument data.classrooms.upsert.0.create.students.connectOrCreate.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
Argument data.classrooms.upsert.0.update.students.upsert.0.create.school.connect of type schoolWhereUniqueInput needs at least one argument.
at Document.validate (/var/task/node_modules/#prisma/client/runtime/index.js:29501:20)
at serializationFn (/var/task/node_modules/#prisma/client/runtime/index.js:33060:19)
at runInChildSpan (/var/task/node_modules/#prisma/client/runtime/index.js:22550:12)
at PrismaClient._executeRequest (/var/task/node_modules/#prisma/client/runtime/index.js:33067:31)
at async PrismaClient._request (/var/task/node_modules/#prisma/client/runtime/index.js:32994:16)
at async profile (/var/task/.next/server/pages/api/user/profile.js:175:27)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:366:9)
at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:481:9)
at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:735:37)
at async Router.execute (/var/task/node_modules/next/dist/server/router.js:247:36) {
clientVersion: '4.9.0'
}
DB Models with relationships: school (1 to many w/students); students (many to many with classrooms); teachers (one to many with students, many to many with classrooms)
Code/Prisma Query
export default async (req, res) => {
...
classroom.students.forEach((student) => {
const totalStudentPoints = student.rewardsRecieved.reduce(
(totalPoints, reward) => {
return totalPoints + reward.pointValue;
},
0
);
groups[student.group.name] += totalStudentPoints;
});
return { ...classroom, groupsTotalPoints: groups };
});
user.classrooms = newClassrooms;
res.json(user);
} else {
console.log("Could Not Find User");
res.status(401).json({
error: "Not authorized",
});
}
}
if (req.method === "PUT") {
const connectStudents = (shouldUpsert) => {
const students = req.body.students;
return students.map((student) => {
const UNSAFEHASH = md5(student.id);
const studentQuery: any = {
where: {
id: student.id,
},
create: {
id: student.id,
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
school: {
connect: {
id: req.body.schoolId,
},
},
group: {
connect: {
id: student.group.id,
},
},
},
};
if (shouldUpsert) {
studentQuery.update = {
firstName: student.firstName,
lastName: student.lastName,
profilePicture: student.profilePicture,
userKey: UNSAFEHASH,
group: {
connect: {
id: student.group.id,
},
},
};
}
return studentQuery;
});
};
try {
const user = await prisma.staff.update({
where: {
id: session.id,
},
data: {
firstName: req.body.firstName,
lastName: req.body.lastName,
classrooms: {
upsert: [
{
where: {
id: req.body.classId || "-1",
},
create: {
// id: req.body.classId,
name: req.body.className,
subject: req.body.classSubject,
students: {
connectOrCreate: connectStudents(false),
},
},
update: {
name: req.body.className,
subject: req.body.classSubject,
students: {
upsert: connectStudents(true),
},
},
},
],
},
},
});
Take a look at the PUT request and the prima.staff.update method more specifically. I was looking at the UPSERT I have there, but I can't figure out what's wrong.

Push an object into a nested array in MongoDB

I've got a head-scratcher here that I'd like to share with you all.
So here's the model:
_id: ObjectId()
name: String,
columns: [
{
name: String,
_id: ObjectId()
tasks: [
{
title: String,
description: String,
status: String,
_id: ObjectId()
subtasks: [
{
title: String,
isCompleted: Boolean,
},
],
},
],
},
],
});
and the query:
exports.createSubtask = (req, res) => {
if (!req.body) {
res.status(400).send({ message: "Task name can not be empty!" });
return;
}
const board = req.params.board;
const column = req.params.column;
const task = req.params.task;
Board.findOneAndUpdate(
{
_id: board,
"columns._id": column,
"columns.tasks._id": task,
},
{
$push: {
"columns.$.tasks.$.subtasks": req.body,
},
}
)
.then((data) => {
if (!data) {
res.status(404).send({
message: `Cannot update Task with id=${task}. Maybe task was not found!`,
});
} else res.send({ message: "Task was updated successfully." });
})
.catch((err) => {
res.status(500).send({
message: "Error updating Task with id=" + task,
});
});
};
I'm trying to push an object into the subtasks array with $push, but Postman is throwing an error.
Any ideas as to what I'm doing wrong? Appreciate the help.
Golden Ratio
However, I was able to successfully push an object into the tasks array with the following query:
exports.createTask = (req, res) => {
if (!req.body) {
res.status(400).send({ message: "Task name can not be empty!" });
return;
}
const board = req.params.board;
const column = req.params.column;
Board.findOneAndUpdate(
{
_id: board,
"columns._id": column,
},
{
$push: {
"columns.$.tasks": req.body,
},
}
)
.then((data) => {
if (!data) {
res.status(404).send({
message: `Cannot update Column with id=${column}. Maybe column was not found!`,
});
} else res.send({ message: "Column was updated successfully." });
})
.catch((err) => {
res.status(500).send({
message: "Error updating Column with id=" + column,
});
});
};
It is not possible to use multiple positional $ for the nested array as mention in docs:
The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value
You should work with the positional filtered operator $[<identifier>].
Board.findOneAndUpdate(
{
_id: board,
"columns._id": column,
"columns.tasks._id": task,
},
{
$push: {
"columns.$.tasks.$[task].subtasks": req.body,
},
},
{
arrayFilters: [
{ "task._id": task }
]
}
)
.then(...);
Note: Ensure that the passed in task is ObjectId type.
Credit to Yong Shun Yong for the help. Through trial and error, I solved the problem with the following code
Board.findOneAndUpdate(
{
_id: board,
"columns._id": column,
},
{
$push: {
"columns.$.tasks.$[].subtasks": req.body,
},
},
{
arrayFilters: [{ "task._id": task }],
}
)

Fastify validate schema with yup - schema.validateSync is not a function

From the Fastify documentation in the section titled Using other validation libraries I'm trying to get yup to validate my schema but I keep getting schema.validateSync is not a function and I don't know why??
I want the schema to still be valid for creating the swagger document but I want to use yup to give me the validation I need.
const yup = require("yup");
const yupOptions = {
strict: false,
abortEarly: false,
stripUnknown: true,
recursive: true,
};
async function isUsernameAvailable(fastify: any, _options: Object) {
const users = fastify.mongo.db.collection("users");
fastify.get(
"/api/v1/onboarding/isUsernameAvailable/:username",
{
schema: {
params: {
type: "object",
properties: {
username: { type: "string", maxLength: 12, minLength: 1 },
},
required: ["username"],
},
response: {
200: {
type: "object",
properties: {
available: {
type: "boolean",
description: "Returns true if username is available",
},
},
},
},
},
validatorCompiler: ({ schema, method, url, httpPart }: any) => {
return function (data: any) {
try {
const result = schema.validateSync(data, yupOptions);
return { value: result };
} catch (e) {
return { error: e };
}
};
},
},
async (request: any, _reply: any) => {
const { username } = request.params;
const foundNUsernames = await users.countDocuments(
{ username },
{ limit: 1 }
);
const available: boolean = foundNUsernames === 0;
return { available };
}
);
}
export { isUsernameAvailable };
if I use the below, the validation works but the swagger doc doesn't build
schema: {
params: yup.object({
username: yup.string().lowercase().max(12).min(1).required(),
}),
}
if I remove the validatorCompiler then I get no errors, swagger does build but I cant use yup
validatorCompiler: ({ schema, method, url, httpPart }: any) => {
return function (data: any) {
try {
const result = schema.validateSync(data, yupOptions);
return { value: result };
} catch (e) {
return { error: e };
}
};
},
}
how can I satisfy both?
Why do I want to use yup? I want to validate emails and transform values into lowercase.

I keep getting [Unhandled promise rejection: Error: Request failed with status code 404] while deleting a post from my API in React Native

I just started coding and I tried to delete a post through my mongoDB API. The code that I used is pretty basic, my API requests all go through a reducer which is set up pretty clear. But when I try to delete a post from my DB, I get the error ''[Unhandled promise rejection: Error: Request failed with status code 404]''. Did I do something wrong here or is this a mongoDB problem? I've included the necessary code.
This is my reducer request:
const deleteWorkout = (dispatch) => {
return async (_id) => {
await trackerApi.delete(`/workouts/${_id}`);
dispatch({ type: "delete_workout", payload: _id });
};
};
This is my complete reducer code:
import createWorkoutDataContext from "./createWorkoutDataContext";
import trackerApi from "../api/tracker";
const workoutReducer = (workouts, action) => {
switch (action.type) {
case "get_workouts":
return action.payload;
case "add_workout":
return [
...workouts,
{
title: action.payload.title,
exercises: action.payload.exercises,
},
];
case "edit_workout":
return workouts.map((Workout) => {
return Workout._id === action.payload.id ? action.payload : Workout;
});
case "delete_workout":
return workouts.filter((Workout) => Workout._id !== action.payload);
default:
return workouts;
}
};
const getWorkouts = (dispatch) => async () => {
const response = await trackerApi.get("/workouts");
dispatch({ type: "get_workouts", payload: response.data });
};
const addWorkout = (dispatch) => {
return async (title, exercises, callback) => {
await trackerApi.post("/workouts", { title, exercises });
if (callback) {
callback();
}
};
};
const editWorkout = (dispatch) => {
return async (title, exercises, _id, callback) => {
await trackerApi.put(`/workouts/${_id}`, { title, exercises });
dispatch({ type: "edit_workout", payload: { _id, title, exercises } });
if (callback) {
callback();
}
};
};
const deleteWorkout = (dispatch) => {
return async (_id) => {
await trackerApi.delete(`/workouts/${_id}`);
dispatch({ type: "delete_workout", payload: _id });
};
};
export const { Context, Provider } = createWorkoutDataContext(
workoutReducer,
{ addWorkout, getWorkouts, deleteWorkout },
[]
);
This is my code where I use the delete function:
const WorkoutListScreen = () => {
const { workouts, getWorkouts, deleteWorkout } = useContext(WorkoutContext);
return (
<View style={styles.container}>
<Text style={styles.pageTitle}>My Workouts</Text>
<NavigationEvents onWillFocus={getWorkouts} />
<FlatList
data={workouts}
keyExtractor={(item) => item._id}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => navigate("WorkoutDetail", { _id: item._id })}
>
<View style={styles.row}>
<Text style={styles.title}>{item.title}</Text>
<TouchableOpacity onPress={() => deleteWorkout(item._id)}>
<Ionicons style={styles.deleteIcon} name="trash-outline" />
</TouchableOpacity>
</View>
</TouchableOpacity>
);
}}
/>
I simply included the deleteWorkout function in my TouchableOpacity, so I suppose that the problem lies within the reducer code?
here is the error I keep getting:
[Unhandled promise rejection: Error: Request failed with status code 404]
at node_modules\axios\lib\core\createError.js:16:14 in createError
at node_modules\axios\lib\core\settle.js:17:22 in settle
at node_modules\axios\lib\adapters\xhr.js:66:12 in onloadend
at node_modules\event-target-shim\dist\event-target-shim.js:818:20 in EventTarget.prototype.dispatchEvent
at node_modules\react-native\Libraries\Network\XMLHttpRequest.js:614:6 in setReadyState
at node_modules\react-native\Libraries\Network\XMLHttpRequest.js:396:6 in __didCompleteResponse
at node_modules\react-native\Libraries\vendor\emitter\_EventEmitter.js:135:10 in EventEmitter#emit
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:414:4 in __callFunction
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:113:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:365:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112:4 in callFunctionReturnFlushedQueue
This is what the objects in my databse look like (through Postman):
{
"userId": "615e06f36ce5e5f1a69c675e",
"title": "Defaults test",
"exercises": [
{
"exerciseTitle": "shadowboxing",
"exerciseProps": {
"time": 0,
"sets": 0,
"reps": 0
},
"_id": "6184c6fa685291fb44778df7"
},
{
"exerciseTitle": "bag workout",
"exerciseProps": {
"time": 4,
"sets": 0,
"reps": 12
},
"_id": "6184c6fa685291fb44778df8"
},
{
"exerciseTitle": "Exercise",
"exerciseProps": {
"time": 4,
"sets": 3,
"reps": 12
},
"_id": "6184c6fa685291fb44778df9"
}
],
"_id": "6184c6fa685291fb44778df6",
"__v": 0
}
I'm gratefull for your help!

ERROR in Read query using n AWS AppSync Chat Starter App written in Angular "Can't find field allMessageConnection"

const message: Message = {
conversationId: conversationId,
content: this.message,
createdAt: id,
sender: this.senderId,
isSent: false,
id: id,
};
this.appsync.hc().then((client) => {
client
.mutate({
mutation: createMessage,
variables: message,
optimisticResponse: () => ({
createMessage: {
...message,
__typename: "Message",
},
}),
update: (proxy, { data: { createMessage: _message } }) => {
const options = {
query: getConversationMessages,
variables: {
conversationId: conversationId,
first: constants.messageFirst,
},
};
// error on below line
const data = proxy.readQuery(options);
const _tmp = unshiftMessage(data, _message);
proxy.writeQuery({ ...options, data: _tmp });
},
})
.then(({ data }) => {
console.log("mutation complete", data);
console.log("mutation complete", data);
})
.catch((err) => console.log("Error creating message", err));
});
Analytics.record("Chat MSG Sent");
}
ERROR
errorHandling.js:7 Error: Can't find field allMessageConnection({"conversationId":"XXXXXXXXXXXXXXXXXXXXXXXXXXX","first":100}) on object {
"me": {
"type": "id",
"generated": false,
"id": "User:XXXXXXXXXXXXXXXXXXX",
"typename": "User"
}
}.