Yup validation based on nested object within nested object - javascript

I currently have an object that looks like the following:
const initialValues = {
created: {
position: 1,
name: 'created',
type: 'timestamp',
desc: 'The date and time the lead is created',
mapping: {
name: '',
defaultValue: '',
map: false
}
}
}
I would like the name within the mapping object to become required when the map value within the map object is set to a value of true. I have attempted this by doing the following:
const validationSchema = yup.object({
created: yup.object().when('mapping.map', {
is: true,
then: yup.object({
mapping: yup.object({
name: yup.string().required('name is required')
})
})
})
})
I believe I'm not tunneling enough in order to accurately set up the validation for the mapping object, any and all help/suggestions would be greatly appreciated.

I found the solution doing the following:
const validationSchema = yup.object({
created: yup.object().shape({
mapping: yup.object().shape({
map: yup.boolean(),
defaultValue: yup.string(),
name: yup.string().when('map', {
is: true,
then: yup.string().required('name is required')
})
})
})
})

Related

How to save an array of strings in mongodb

I have found a few similar questions on stack overflow like this one:
How to save array of Strings in Node Mongodb
Mongoose - Save array of strings
but I cant figure out why my method is not working
I am trying to save the string of arrays "jobType".
context: I am creating an app where people can post jobs.
each job can have multiple types.
here is my job model::
const mongoose = require("mongoose");
const postSchema = mongoose.Schema({
content: { type: String, required: true },
imagePath: { type: String, required: true },
state: { type: String, required: true },
substate: { type: String, required: true },
address: { type: String, required: true },
jobType: { type: [String] },
creator: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }
});
module.exports = mongoose.model("Job", postSchema);
this is the API used to save the data on MongoDB:
I am 100% sure that the data is getting to the API correctly.
the parameter "req.body.jobtype" contains all the info as a string.
I am trying to use JSON.parse to change the string into an array but its not working.
when I check MongoDB, an empty array is being stored
const Job = require("../models/job");
exports.createJob = (req, res, next) => {
console.log('create job api hit')
const url = req.protocol + "://" + req.get("host");
const post = new Job({
content: req.body.content,
imagePath: url + "/images/" + req.file.filename,
creator: req.userData.userId,
state: 'new',
substate: 'new',
address: req.body.address,
jobtype: JSON.parse(req.body.jobtype) // fix: not storing correctly
});
post
.save()
.then(createdJob => {
res.status(201).json({
message: "Job added successfully",
post: {
...createdJob,
'pecker':'pecker hecks out',
id: createdJob._id
}
});
})
.catch(error => {
res.status(500).json({
message: JSON.stringify(error)
});
});
};
You have a typo. In your model, you defined jobType property, but when saving the data, you are passing it as jobtype.
So, instead of this:
jobtype: JSON.parse(req.body.jobtype)
Do this:
jobType: JSON.parse(req.body.jobtype)

How to return an error when $addToSet does not add an item because it already exists in Mongoose?

I have the following schema which contains a property with an array:
const projectSchema = new mongoose.Schema(
{
title: {
type: String,
required: [true, "Please add a title"],
},
users: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
},
);
In my project controller, I'm trying to add users to this array without getting a duplicate user. So I use $addToSet. It works fine but it doesn't return an error when there is a duplicate user.
const project = await Project.findOneAndUpdate(
{ _id: id },
{ $addToSet: { users: userID } },
{ new: true }
);
How can I detect that it didn't add a user (because the user already exists in the array) and return an error?

Nested JSON object not saving to database MongoDB

I have three mongo schemas, each nest into one another. The main one has a nested JSON, which also has a nested JSON inside that. However, when the User is saved using the main Schema, the other two nested schemas aren't being saved with their default values, why? Here's an example of my three schemas (just an example data structure):
const userContacts = new mongoose.Schema({
user1PhoneNumber: {
type: Number,
default: 0
},
user2PhoneNumber: {
type: Number,
default: 0
}
})
const contact = new mongoose.Schema({
phoneNumber: {
type: Number,
default: 0
},
contacts: {
type: userContacts
}
})
const finalUserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
max: 255
},
email: {
type: String,
required: true,
max: 255,
},
password: {
type: String,
required: true,
min: 10,
max: 1024,
},
contactDetails: {
type: contact
}
})
module.exports = mongoose.model('User', finalUserSchema);
When the user is first created using the mongoose model, the values aren't set as they will be used later on...but they should still appear in the database with their default values:
const user = new User({
username: req.body.username,
email: req.body.email,
password: hashedPassword,
});
What gets saved in the database:
Where is the contactDetials nested JSON object with it's default values, I shouldn't have to provide any data when I first save the user as it should just use the data model with its default values?
May you should try this:
contactDetails: contact
instead of:
contactDetails: {type: contact}
same for Contacts

I need to unstructure an object to update the variables defined in data

it's my first post. I need to destructure to update a variable defined in "data", I have the following code snippets. I'm using VUE.
data: () => ({
id: '',
phone: '',
email: ''
}),
methods: {
async getId(){
{this.id, this.email, this.phone} = this.$route.query.item
}
}
Actually you can assign to existing variables.
The syntax is just a little weird.
This should work
({id: this.id, phone: this.phone, email: this.email} = this.$route.query.item)
Here's a working example
You can't destructure to existing props but to new ones only:
data () {
return {
item: {
id: '',
phone: '',
email: ''
}
}
},
...
methods: {
async getId(){
{ id, email, phone } = this.$route.query.item
Object.assign(this.item, { id, email, phone })

Joi validation multiple AND conditions

I'm trying to validate my target object with following conditions:
if (target.company === `GP` AND one of target.documents type equals `full`) {
one of target.documents type must equals `part-should-be-error`
} else {
throw new Error()
}
In this example, validation doesn't return any errors, but it should, because of 'part' !== 'part-should-be-error'
I tried https://stackoverflow.com/a/53647449/10432429 but it doesn't work with Joi v15
Since I can't merge array schema with alternative schema, all that I can to do is use $ to get global context, but seems that it doesn't work too
I have codebase on Joi v15.1.1, so please install same version
npm i #hapi/joi#15.1.1
const Joi = require('#hapi/joi');
(async () => {
const target = {
name: 'Jeff',
company: 'GP',
documents: [
{type: 'full', value: 'apple'},
{type: 'part', value: 'tesla'},
],
};
const documents = Joi.object().keys({
type: Joi.string().valid(['full', 'part', 'empty']),
value: Joi.string().min(1).max(40)
.required(),
}).required();
const schema = Joi.object()
.keys({
name: Joi.string().min(1).max(20)
.required(),
company: Joi.string().valid(['GP', 'QW']),
documents: Joi.array().items(documents).min(1)
.when('$', {
is: Joi.object().keys({
company: Joi.string().valid(['GP']),
documents: Joi.array().has(Joi.object({type: Joi.string().valid('full')}).unknown().required()),
}).unknown().required(),
then: Joi.array().has(Joi.object({type: Joi.string().valid(['part-should-be-error'])}).unknown()).required(),
})
.required(),
});
await Joi.validate(target, schema, {context: target});
})();
If I do sth wierd, please feel free to show another way how to solve this

Categories