Simple Schema error in Meteor - javascript

I am using the meteor accounts and simple schema for users to register and enter their profile information in my app. I defined a schema for users and attached a schema for address to it. However, when I go to register an account, I keep getting the error "Address required" although I filled out all the required fields for address. Here's my schema:
Schemas.UserAddress = new SimpleSchema({ //UserAddress schema defined
streetAddress: {
type: String,
max: 100,
optional: false
},
city: {
type: String,
max: 50,
optional: false
},
state: {
type: String,
regEx: /^A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]$/,
optional: false
},
zipCode: {
type: String,
regEx: /^[0-9]{5}$/,
optional: false
}
});
var Schemas = {};
Schemas.UserProfile = new SimpleSchema({
companyName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}$/,
optional: false
},
tireMarkup: {
type: Number,
optional: true,
min: 1
},
phoneNum: {
type: String,
regEx: /^[(]{0,1}[0-9]{3}[)]{0,1}[-\s\.]{0,1}[0-9]{3}[-\s\.]{0,1}[0-9]{4}$/,
optional: false
},
confirmed: {
type: Boolean,
optional: true
},
});
Schemas.User = new SimpleSchema({
emails: {
type: [Object],
optional: false
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schemas.UserProfile,
optional: false
},
address: { //Attach user address schema
type: Schemas.UserAddress,
optional: false
},
services: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schemas.User);
Here is my accounts config which creates the sign up form:
Meteor.startup(function () {
AccountsEntry.config({
logo: '', // if set displays logo above sign-in options
termsUrl: '/terms-of-use', // if set adds link to terms 'you agree to ...' on sign-up page
homeRoute: '/', // mandatory - path to redirect to after sign-out
dashboardRoute: '/dashboard/', // mandatory - path to redirect to after successful sign-in
profileRoute: '/profile',
passwordSignupFields: 'EMAIL_ONLY',
showOtherLoginServices: true, // Set to false to hide oauth login buttons on the signin/signup pages. Useful if you are using something like accounts-meld or want to oauth for api access
extraSignUpFields: [
{
field: "companyName",
label: "Company Name",
placeholder: "Petrocon",
type: "text",
required: true
},
{
field: "firstName",
label: "First Name",
placeholder: "John",
type: "text",
required: true
},
{
field: "lastName",
label: "Last Name",
placeholder: "Nguyen",
type: "text",
required: true
},
{ field: "streetAddress",
label: "Street Address",
placeholder: "12345 Main Street",
type: "text",
required: true
},
{ field: "city",
label: "City",
placeholder: "Springfield",
type: "text",
required: true
},
{ field: "state",
label: "State",
placeholder: "Missouri",
type: "text",
required: true
},
{ field: "zipCode",
label: "Zip Code",
placeholder: "65801",
type: "text",
required: true
},
{
field: "phoneNum",
label: "Contact Number",
placeholder: "316-000-0000",
type: "text",
required: true
}
]
});
});
As you can see, I defined all of the fields in the address schema in AccountsEntry.config.. therefore I don't know why when I enter all the information in the form, I get the error 'address required'. Does anyone know what's going on? Thank you in advance!

Looks like you're using the accounts-entry package. You can see the code where the account is created in this file:
https://github.com/Differential/accounts-entry/blob/9aac00cb3c67afcbb1cc990c7af1f2c7607a2337/server/entry.coffee
Line 29 looks like this:
profile: _.extend(profile, user.profile)
If you debug and look at the value of profile after the extend method is called, you'll see this:
{
"companyName": "Petrocon",
"firstName": "John",
"lastName": "Nguyen",
"streetAddress": "12345 Main Street",
"city": "Springfield",
"state": "Missouri",
"zipCode": "65801",
"phoneNum": "316-000-0000"
}
There is no property named "address" for your Schemas.User schema.
There might be some slick way to do what you're looking for, but the easiest approach is to just get rid of the Schemas.UserAddress schema. Move those properties (streetAddress, city, state, zipCode) into the Schemas.UserProfile schema and it will work.

Related

How to add phone number validation in AJV

I have a form field called phone number with country code. So when the user inputs the phone, it is required to validate the phone number with its country code. I did it before with Yup and yup-phone libraries which use google's libphonenumber. However, I found no way to do it with AJV. Here is my schema.
export const ProfileRequestSchema = {
type: "object",
properties: {
firstName: {
type: "string",
minLength: 1,
},
lastName: {
type: "string",
minLength: 1,
},
countryCode: {
minLength: 1,
type: "string",
},
phoneNumber: {
minLength: 1,
type: "string",
},
},
//additionalProperties: false,
required: [
"firstName",
"lastName",
"countryCode",
"phoneNumber",
],
errorMessage: {
type: "should be an object",
properties: {
firstName: t`First name is required and must be a string`,
lastName: t`Last name is required and must be a string`,
countryCode: t`Country Code is required and must be a string`,
phoneNumber: t`Phone number is required and must be a string`,
},
},
};
export const ProfileRequestValidator = ajv.compile(ProfileRequestSchema);
So, is there any way to integrate phone number validator library like libphonenumber-js with AJV?
TIA

How Save Nested Array into Mongodb Using Mongoose schema?

Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
My data Look Like That
{
"name": "This is Name countru",
"type": "Hotel",
"country": "Bangladesh",
"city": "Chittagong",
"address": "22 D Block, Kolpolok Residense, Bakulia,",
"distance": "Chittagong",
"title": "tis is best hotel",
"desc": "Pamper yourself with a visit to the spa, which offers massages, body treatments, and facials. You can take advantage of recreational amenities such as an outdoor pool, a spa tub, and a sauna. Additional features at this hotel include complimentary wireless Internet access, concierge services, and a banquet hall. Grab a bite at The Exchange, one of the hotel's 3 restaurants, or stay in and take advantage of the 24-hour room service. Relax with your favorite drink at the bar/lounge or the poolside bar. Featured amenities include a business center, dry cleaning/laundry services, and a 24-hour front desk. Free valet parking is available onsite. Make yourself at home in one of the 241 air-conditioned rooms featuring LED televisions. Complimentary wireless Internet access keeps you connected, and satellite programming is available for your entertainment. Private bathrooms with separate bathtubs and showers feature hair dryers and slippers. Conveniences include phones, as well as safes and coffee/tea makers. Distances a",
"cheapestPrice": "105",
"rooms": [
"629dd3bae549560b971612da",
"629dd418e549560b971612df",
"629dd481e549560b971612ea",
"629dd4b3e549560b971612f0",
"629dd4b4e549560b971612f6",
"629dec61e549560b9716139f"
],
"photos": [
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/jxsbi7r26cyqgnwg65ni.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222494/upload/bybbcdb8iluy0t7smf1u.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/pzfzk3umv5agumt30ygo.jpg"
],
"allFacilities": [
{
"hotelfacilities": [
"dsds",
" sdsd",
" sdd"
]
},
{
"roomfacilities": [
"sdsd",
" dss",
" dss"
]
},
{
"wellnessSpa": [
"sds",
" dsd",
" sdsd",
" sds"
]
}
]
}
My Mongoose Schema Look Like That
import mongoose from "mongoose";
const HotelSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: [String],
},
photos: {
type: [String],
},
allFacilities: {
type: [String],
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});
export default mongoose.model("Hotel", HotelSchema)
use "type: Array" for rooms, photos and allFacilities
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: Array,
},
photos: {
type: Array,
},
allFacilities: {
type: Array,
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});

How to use mongoose transactions with updateMany?

I am using the mongoose updateMany() method and I also want to keep it a part of transaction. The documentation shows the example of save() where I can do something like Model.save({session: mySession}) but don't really know how to use it with for example Model.updateMany()
UPDATE:
For example I have two models called SubDomain and Service and they look like this respectively:
SUB-DOMAIN
{
name: {
type: String,
required: true,
},
url: {
type: String,
required: true,
unique: true,
},
services: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Service",
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
}
SERVICE:
{
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: { type: Number },
tags: { type: Array },
packages: [
{
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
},
],
map: { type: String },
isHidden: {
type: Boolean,
required: true,
default: false,
},
sortingOrder: { type: Number },
isForDomain: { type: Boolean, required: false, default: false },
isForSubDomain: { type: Boolean, required: false, default: false },
subDomains: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "SubDomain",
},
],
}
Now the main field here is the services field in SubDomain and subDomains field in Service.
The complicated part😅:
Whenever the user wants to create new service, I want to $push that service's _id into the array of services of all the subDomains inside that new service
And for that, I am using the updateMany() like this:
const sess = await mongoose.startSession();
sess.startTransaction();
const newService = new Service({
_id: mongoose.Types.ObjectId(),
subDomains: req.body.subDomains
...foo
})
await SubDomain.updateMany(
{ _id: { $in: req.body.subDomains } },
{ $push: { services: newService._id } }
);
The problem starts here, of course I can do:
newService.save({session: sess})
but how do I keep my SubDomain's updateMany in the same transaction (i.e sess)
I know my example is difficult to wrap your head around but I have tried to pick a simplest example rather than copying the exact same code which would have been a lot more difficult

How to get the model/schema name from subdocument?

I have the following schema and subschema:
The child schema:
const SettingSchema = new Schema({
settingIdentifier: {
type: String,
required: true
},
shareLink: {
type: String,
required: true
},
downloadLink: {
type: String,
required: true
},
direction: {
type: String,
required: true
}
});
And the parent schema:
const DeviceSchema = new Schema({
id: {
type: String,
required: true
},
store: {
type: String,
required: true
},
storeName: {
type: String,
required: true
},
deviceInfo: {
type: String,
required: true
},
contentSettings:{
type:[SettingSchema],
required: true
}
})
In my code, I want to get the child schema name from the retrieved document.
For example, I can get the document as such:
Device.findOne({ deviceInfo: "someValue" }).then(device => {
// device is the retrieved document
// with this device object, how do I get the device[settings] schema name?
// device[settings] is an array of SettingSchema with possibly multiple members
// Expected output : "SettingSchema"
});
So, how do I get the schema name of the subdocument "settings" when I have the "device" object?
Many thanks in advance.
Edit:
I'm attaching the console.log to show what device contains after Device.findOne.
{
"_id": "5ea034d07d865e38c0d4ed6f",
"id": "1a89d59800a72e39",
"store": 1,
"storeName": "Singapore Store",
"deviceInfo": "test device2",
"contentSettings": [
{
"settingIdentifier": "NewYearEvent",
"shareLink": "share1",
"downloadLink": "dl1",
"direction": "D"
},
{
"settingIdentifier": "EasterEvent",
"shareLink": "share2",
"downloadLink": "dl2",
"direction": "H"
}
],
"__v": 0
}
So Device.findOne gets a device instance from the database and it contains the data, but I don't see the metadata to identify the type or schema name of device itself, or its members

Mongoose, enforce changes to schema after mongoose.model('core_user').schema = new mongoose.schema(...)

I am using the Express-Restify-Mongoose library to generate all of my endpoints for a REST api.
I am storing my schemas in a collection named 'core_schema.' Each time the server starts all records within that collection are grabbed using a find() method. This provides an array of all available collections with defined schemas.
db.on('open', function(){
findDocs('core_schema', {}, function(docs){
var tempString = JSON.stringify(docs);
var tempObj = JSON.parse(tempString);
for (var i = 0; i < tempObj.length; i++) {
var temp_schema = new mongoose.Schema(tempObj[i].schema_data, { collection: tempObj[i].collection_name });
var temp_model = mongoose.model(tempObj[i].collection_name, temp_schema);
restify.serve(router, temp_model, { plural: false, name: tempObj[i].collection_name, preCreate: setDateTimes });
}
});
});
I would like to be able to make changes to the schema to enforce new POST rules, but when I try to use a test example like:
mongoose.model('core_user').schema = new mongoose.Schema({
update_count: { type: "String", required: false },
created_date: { type: "String", required: false },
created_by: { type: "String", required: false },
updated_date: { type: "String", required: false },
updated_by: { type: "String", required: false },
first_name: { type: "String", required: true },
last_name: { type: "String", required: true },
username: { type: "String", required: true },
password: { type: "String", required: true },
somethingElse: { type: "String", required: true }
}, {collection: 'core_user'})
Where 'somethingElse' is the new field I am trying to enforce it does not enforce it. What am I doing wrong? Is there no way to update the model to use the new schema?
To update a Mongoose schema, you'll need to use the Schema.add method. You can update the schema for a model using the code below:
mongoose.model('core_user').schema.add({ somethingElse: {
type: 'String',
required: true
}});

Categories