Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ module.exports = function cast(schema, obj, options, context) {
}

if (geo) {
const numbertype = new Types.Number('__QueryCasting__');
const numbertype = new Types.Number('__QueryCasting__', null, null, schema);
let value = val[geo];

if (val.$maxDistance != null) {
Expand Down
10 changes: 10 additions & 0 deletions lib/helpers/discriminator/mergeDiscriminatorSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const schemaMerge = require('../schema/merge');
const specialProperties = require('../../helpers/specialProperties');
const isBsonType = require('../../helpers/isBsonType');
const ObjectId = require('../../types/objectid');
const SchemaType = require('../../schemaType');
const isObject = require('../../helpers/isObject');
/**
* Merges `from` into `to` without overwriting existing properties.
Expand Down Expand Up @@ -69,6 +70,15 @@ module.exports = function mergeDiscriminatorSchema(to, from, path, seen) {
} else if (isBsonType(from[key], 'ObjectId')) {
to[key] = new ObjectId(from[key]);
continue;
} else if (from[key] instanceof SchemaType) {
if (to[key] == null) {
to[key] = from[key].clone();
}
// For container types with nested schemas, we need to continue to the
// recursive merge below to properly merge the nested schemas
if (!from[key].$isMongooseDocumentArray && !from[key].$isSingleNested) {
continue;
}
}
}
mergeDiscriminatorSchema(to[key], from[key], path ? path + '.' + key : key, seen);
Expand Down
2 changes: 1 addition & 1 deletion lib/helpers/query/castUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
if (obj[key] == null) {
throw new CastError('String', obj[key], `${prefix}${key}.$rename`);
}
const schematype = new SchemaString(`${prefix}${key}.$rename`);
const schematype = new SchemaString(`${prefix}${key}.$rename`, null, null, schema);
obj[key] = schematype.castForQuery(null, obj[key], context);
continue;
}
Expand Down
62 changes: 10 additions & 52 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
let name;

if (utils.isPOJO(type) || type === 'mixed') {
return new MongooseTypes.Mixed(path, obj);
return new MongooseTypes.Mixed(path, obj, null, this);
}

if (Array.isArray(type) || type === Array || type === 'array' || type === MongooseTypes.Array) {
Expand All @@ -1595,7 +1595,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
`${path}: new Schema(...)`);
}
}
return new MongooseTypes.DocumentArray(path, cast, obj);
return new MongooseTypes.DocumentArray(path, cast, obj, null, this);
}
if (cast &&
cast[options.typeKey] &&
Expand All @@ -1612,14 +1612,14 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
`${path}: new Schema(...)`);
}
}
return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast, this);
}
if (typeof cast !== 'undefined') {
if (Array.isArray(cast) || cast.type === Array || cast.type == 'Array') {
if (cast && cast.type == 'Array') {
cast.type = Array;
}
return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj, null, this);
}
}

Expand Down Expand Up @@ -1660,10 +1660,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {

const childSchema = new Schema(castFromTypeKey, childSchemaOptions);
childSchema.$implicitlyCreated = true;
return new MongooseTypes.DocumentArray(path, childSchema, obj);
return new MongooseTypes.DocumentArray(path, childSchema, obj, null, this);
} else {
// Special case: empty object becomes mixed
return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj);
return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj, null, this);
}
}

Expand All @@ -1672,7 +1672,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
? cast[options.typeKey]
: cast;
if (Array.isArray(type)) {
return new MongooseTypes.Array(path, this.interpretAsType(path, type, options), obj);
return new MongooseTypes.Array(path, this.interpretAsType(path, type, options), obj, null, this);
}

name = typeof type === 'string'
Expand All @@ -1696,11 +1696,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
}
}

return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options);
return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options, this);
}

if (type && type.instanceOfSchema) {
return new MongooseTypes.Subdocument(type, path, obj);
return new MongooseTypes.Subdocument(type, path, obj, this);
}

if (Buffer.isBuffer(type)) {
Expand Down Expand Up @@ -1739,53 +1739,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
'https://bit.ly/mongoose-schematypes for a list of valid schema types.');
}

if (name === 'Union') {
obj.parentSchema = this;
}
const schemaType = new MongooseTypes[name](path, obj, options);

if (schemaType.$isSchemaMap) {
createMapNestedSchemaType(this, schemaType, path, obj, options);
}
const schemaType = new MongooseTypes[name](path, obj, options, this);

return schemaType;
};

/*!
* ignore
*/

function createMapNestedSchemaType(schema, schemaType, path, obj, options) {
const mapPath = path + '.$*';
let _mapType = { type: {} };
if (utils.hasUserDefinedProperty(obj, 'of')) {
const isInlineSchema = utils.isPOJO(obj.of) &&
Object.keys(obj.of).length > 0 &&
!utils.hasUserDefinedProperty(obj.of, schema.options.typeKey);
if (isInlineSchema) {
_mapType = { [schema.options.typeKey]: new Schema(obj.of) };
} else if (utils.isPOJO(obj.of)) {
_mapType = Object.assign({}, obj.of);
} else {
_mapType = { [schema.options.typeKey]: obj.of };
}

if (_mapType[schema.options.typeKey] && _mapType[schema.options.typeKey].instanceOfSchema) {
const subdocumentSchema = _mapType[schema.options.typeKey];
subdocumentSchema.eachPath((subpath, type) => {
if (type.options.select === true || type.options.select === false) {
throw new MongooseError('Cannot use schema-level projections (`select: true` or `select: false`) within maps at path "' + path + '.' + subpath + '"');
}
});
}

if (utils.hasUserDefinedProperty(obj, 'ref')) {
_mapType.ref = obj.ref;
}
}
schemaType.$__schemaType = schema.interpretAsType(mapPath, _mapType, options);
}

/**
* Iterates the schemas paths similar to Array#forEach.
*
Expand Down
13 changes: 9 additions & 4 deletions lib/schema/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ const emptyOpts = Object.freeze({});
* @param {SchemaType} cast
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaArray(key, cast, options, schemaOptions) {
function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
// lazy load
EmbeddedDoc || (EmbeddedDoc = require('../types').Embedded);

Expand Down Expand Up @@ -92,7 +93,11 @@ function SchemaArray(key, cast, options, schemaOptions) {
!caster.$isArraySubdocument &&
!caster.$isSchemaMap) {
const path = this.caster instanceof EmbeddedDoc ? null : key;
this.caster = new caster(path, castOptions);
if (caster === SchemaArray) {
this.caster = new caster(path, castOptions, schemaOptions, null, parentSchema);
} else {
this.caster = new caster(path, castOptions, schemaOptions, parentSchema);
}
} else {
this.caster = caster;
if (!(this.caster instanceof EmbeddedDoc)) {
Expand All @@ -105,7 +110,7 @@ function SchemaArray(key, cast, options, schemaOptions) {

this.$isMongooseArray = true;

SchemaType.call(this, key, options, 'Array');
SchemaType.call(this, key, options, 'Array', parentSchema);

let defaultArr;
let fn;
Expand Down Expand Up @@ -494,7 +499,7 @@ SchemaArray.prototype.discriminator = function(...args) {

SchemaArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.path, this.caster, options, this.schemaOptions);
const schematype = new this.constructor(this.path, this.caster, options, this.schemaOptions, this.parentSchema);
schematype.validators = this.validators.slice();
if (this.requiredValidator !== undefined) {
schematype.requiredValidator = this.requiredValidator;
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/bigint.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeD
*
* @param {String} path
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaBigInt(path, options) {
SchemaType.call(this, path, options, 'BigInt');
function SchemaBigInt(path, options, _schemaOptions, parentSchema) {
SchemaType.call(this, path, options, 'BigInt', parentSchema);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeD
*
* @param {String} path
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaBoolean(path, options) {
SchemaType.call(this, path, options, 'Boolean');
function SchemaBoolean(path, options, _schemaOptions, parentSchema) {
SchemaType.call(this, path, options, 'Boolean', parentSchema);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ const CastError = SchemaType.CastError;
*
* @param {String} key
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaBuffer(key, options) {
SchemaType.call(this, key, options, 'Buffer');
function SchemaBuffer(key, options, _schemaOptions, parentSchema) {
SchemaType.call(this, key, options, 'Buffer', parentSchema);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ const CastError = SchemaType.CastError;
*
* @param {String} key
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaDate(key, options) {
SchemaType.call(this, key, options, 'Date');
function SchemaDate(key, options, _schemaOptions, parentSchema) {
SchemaType.call(this, key, options, 'Date', parentSchema);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/decimal128.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ const isBsonType = require('../helpers/isBsonType');
*
* @param {String} key
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaDecimal128(key, options) {
SchemaType.call(this, key, options, 'Decimal128');
function SchemaDecimal128(key, options, _schemaOptions, parentSchema) {
SchemaType.call(this, key, options, 'Decimal128', parentSchema);
}

/**
Expand Down
26 changes: 19 additions & 7 deletions lib/schema/documentArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ let Subdocument;
* @param {Schema} schema
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaArray
* @api public
*/

function SchemaDocumentArray(key, schema, options, schemaOptions) {
function SchemaDocumentArray(key, schema, options, schemaOptions, parentSchema) {
if (schema.options && schema.options.timeseries) {
throw new InvalidSchemaOptionError(key, 'timeseries');
}
Expand All @@ -59,7 +60,7 @@ function SchemaDocumentArray(key, schema, options, schemaOptions) {
const EmbeddedDocument = _createConstructor(schema, options);
EmbeddedDocument.prototype.$basePath = key;

SchemaArray.call(this, key, EmbeddedDocument, options);
SchemaArray.call(this, key, EmbeddedDocument, options, null, parentSchema);

this.schema = schema;
// EmbeddedDocument schematype options
Expand All @@ -83,10 +84,15 @@ function SchemaDocumentArray(key, schema, options, schemaOptions) {
}

const $parentSchemaType = this;
this.$embeddedSchemaType = new DocumentArrayElement(key + '.$', {
...(schemaOptions || {}),
$parentSchemaType
});
this.$embeddedSchemaType = new DocumentArrayElement(
key + '.$',
{
...(schemaOptions || {}),
$parentSchemaType
},
schemaOptions,
parentSchema
);

this.$embeddedSchemaType.caster = this.Constructor;
this.$embeddedSchemaType.schema = this.schema;
Expand Down Expand Up @@ -529,7 +535,13 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {

SchemaDocumentArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
const schematype = new this.constructor(
this.path,
this.schema,
options,
this.schemaOptions,
this.parentSchema
);
schematype.validators = this.validators.slice();
if (this.requiredValidator !== undefined) {
schematype.requiredValidator = this.requiredValidator;
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/documentArrayElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ const getConstructor = require('../helpers/discriminator/getConstructor');
*
* @param {String} path
* @param {Object} options
* @param {Object} _schemaOptions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param {Object} _schemaOptions
* @param {Object} schemaOptions

The other schematypes dont refer to it with underscore in the jsdoc when unused (re SchemaBoolean, SchemaBuffer, etc)

* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaDocumentArrayElement(path, options) {
function SchemaDocumentArrayElement(path, options, _schemaOptions, parentSchema) {
this.$parentSchemaType = options && options.$parentSchemaType;
if (!this.$parentSchemaType) {
throw new MongooseError('Cannot create DocumentArrayElement schematype without a parent');
}
delete options.$parentSchemaType;

SchemaType.call(this, path, options, 'DocumentArrayElement');
SchemaType.call(this, path, options, 'DocumentArrayElement', parentSchema);

this.$isMongooseDocumentArrayElement = true;
}
Expand Down
6 changes: 4 additions & 2 deletions lib/schema/double.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ const createJSONSchemaTypeDefinition = require('../helpers/createJSONSchemaTypeD
*
* @param {String} path
* @param {Object} options
* @param {Object} schemaOptions
* @param {Schema} parentSchema
* @inherits SchemaType
* @api public
*/

function SchemaDouble(path, options) {
SchemaType.call(this, path, options, 'Double');
function SchemaDouble(path, options, _schemaOptions, parentSchema) {
SchemaType.call(this, path, options, 'Double', parentSchema);
}

/**
Expand Down
Loading
Loading