-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
se agregan las condiciones parciales para las condiciones
- Loading branch information
Juan Carlos Muñoz
committed
Jul 9, 2019
1 parent
c1e8db6
commit 07643b0
Showing
2 changed files
with
113 additions
and
109 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,129 @@ | ||
'use strict'; | ||
"use strict"; | ||
|
||
const each = require('lodash.foreach'); | ||
const get = require('lodash.get'); | ||
const each = require("lodash.foreach"); | ||
const get = require("lodash.get"); | ||
|
||
// Function typecheck helper | ||
const isFunc = (val) => typeof val === 'function'; | ||
const isFunc = val => typeof val === "function"; | ||
|
||
const deepPath = function(schema, pathName) { | ||
let path; | ||
const paths = pathName.split('.'); | ||
let path; | ||
const paths = pathName.split("."); | ||
|
||
if (paths.length > 1) { | ||
pathName = paths.shift(); | ||
} | ||
if (paths.length > 1) { | ||
pathName = paths.shift(); | ||
} | ||
|
||
if (isFunc(schema.path)) { | ||
path = schema.path(pathName); | ||
} | ||
if (isFunc(schema.path)) { | ||
path = schema.path(pathName); | ||
} | ||
|
||
if (path && path.schema) { | ||
path = deepPath(path.schema, paths.join('.')); | ||
} | ||
if (path && path.schema) { | ||
path = deepPath(path.schema, paths.join(".")); | ||
} | ||
|
||
return path; | ||
return path; | ||
}; | ||
|
||
// Export the mongoose plugin | ||
module.exports = function(schema, options) { | ||
options = options || {}; | ||
const type = options.type || 'unique'; | ||
const message = options.message || 'Error, expected `{PATH}` to be unique. Value: `{VALUE}`'; | ||
|
||
// Mongoose Schema objects don't describe default _id indexes | ||
// https://github.com/Automattic/mongoose/issues/5998 | ||
const indexes = [[{ _id: 1 }, { unique: true }]].concat(schema.indexes()); | ||
|
||
// Dynamically iterate all indexes | ||
each(indexes, (index) => { | ||
const indexOptions = index[1]; | ||
|
||
if (indexOptions.unique) { | ||
const paths = Object.keys(index[0]); | ||
each(paths, (pathName) => { | ||
// Choose error message | ||
const pathMessage = typeof indexOptions.unique === 'string' ? indexOptions.unique : message; | ||
|
||
// Obtain the correct path object | ||
const path = deepPath(schema, pathName) || schema.path(pathName); | ||
|
||
if (path) { | ||
// Add an async validator | ||
path.validate(function() { | ||
return new Promise((resolve) => { | ||
const isSubdocument = isFunc(this.ownerDocument); | ||
const isQuery = this.constructor.name === 'Query'; | ||
const parentDoc = isSubdocument ? this.ownerDocument() : this; | ||
const isNew = typeof parentDoc.isNew === 'boolean' ? parentDoc.isNew : !isQuery; | ||
|
||
const conditions = {}; | ||
each(paths, (name) => { | ||
let pathValue; | ||
|
||
// If the doc is a query, this is a findAndUpdate | ||
if (isQuery) { | ||
pathValue = get(this, '_update.' + name) || get(this, '_update.$set.' + name); | ||
} else { | ||
pathValue = get(this, isSubdocument ? name.split('.').pop() : name); | ||
} | ||
|
||
// Wrap with case-insensitivity | ||
if (get(path, 'options.uniqueCaseInsensitive') || indexOptions.uniqueCaseInsensitive) { | ||
// Escape RegExp chars | ||
pathValue = pathValue.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); | ||
pathValue = new RegExp('^' + pathValue + '$', 'i'); | ||
} | ||
|
||
conditions[name] = pathValue; | ||
}); | ||
|
||
if (!isNew) { | ||
// Use conditions the user has with find*AndUpdate | ||
if (isQuery) { | ||
each(this._conditions, (value, key) => { | ||
conditions[key] = { $ne: value }; | ||
}); | ||
} else if (pathName !== '_id') { | ||
// if it's not new then it always has _id | ||
conditions._id = { $ne: this._id }; | ||
} else { | ||
// if is not new and is not query and the pathName is _id then is the same document no need to check anything | ||
return resolve(true); | ||
} | ||
} | ||
|
||
// Obtain the model depending on context | ||
// https://github.com/Automattic/mongoose/issues/3430 | ||
// https://github.com/Automattic/mongoose/issues/3589 | ||
let model; | ||
if (isQuery) { | ||
model = this.model; | ||
} else if (isSubdocument) { | ||
model = this.ownerDocument().model(this.ownerDocument().constructor.modelName); | ||
} else if (this.constructor.modelName) { | ||
// if the constructor has modelName then the constructor is the model | ||
model = this.constructor; | ||
} | ||
|
||
// Is this model a discriminator and the unique index is on the whole collection, | ||
// not just the instances of the discriminator? If so, use the base model to query. | ||
// https://github.com/Automattic/mongoose/issues/4965 | ||
if (model.baseModelName && indexOptions.partialFilterExpression === null) { | ||
model = model.db.model(model.baseModelName); | ||
} | ||
|
||
model.find(conditions).countDocuments((err, count) => { | ||
resolve(count === 0); | ||
}); | ||
}); | ||
}, pathMessage, type); | ||
options = options || {}; | ||
const type = options.type || "unique"; | ||
const message = options.message || "Error, expected `{PATH}` to be unique. Value: `{VALUE}`"; | ||
|
||
// Mongoose Schema objects don't describe default _id indexes | ||
// https://github.com/Automattic/mongoose/issues/5998 | ||
const indexes = [[{_id: 1}, {unique: true}]].concat(schema.indexes()); | ||
|
||
// Dynamically iterate all indexes | ||
each(indexes, index => { | ||
const indexOptions = index[1]; | ||
|
||
if (indexOptions.unique) { | ||
const paths = Object.keys(index[0]); | ||
each(paths, pathName => { | ||
// Choose error message | ||
const pathMessage = typeof indexOptions.unique === "string" ? indexOptions.unique : message; | ||
|
||
// Obtain the correct path object | ||
const path = deepPath(schema, pathName) || schema.path(pathName); | ||
|
||
if (path) { | ||
// Add an async validator | ||
path.validate( | ||
function() { | ||
return new Promise(resolve => { | ||
const isSubdocument = isFunc(this.ownerDocument); | ||
const isQuery = this.constructor.name === "Query"; | ||
const parentDoc = isSubdocument ? this.ownerDocument() : this; | ||
const isNew = typeof parentDoc.isNew === "boolean" ? parentDoc.isNew : !isQuery; | ||
|
||
const conditions = indexOptions.partialFilterExpression || {}; | ||
each(paths, name => { | ||
let pathValue; | ||
|
||
// If the doc is a query, this is a findAndUpdate | ||
if (isQuery) { | ||
pathValue = get(this, "_update." + name) || get(this, "_update.$set." + name); | ||
} else { | ||
pathValue = get(this, isSubdocument ? name.split(".").pop() : name); | ||
} | ||
|
||
// Wrap with case-insensitivity | ||
if (get(path, "options.uniqueCaseInsensitive") || indexOptions.uniqueCaseInsensitive) { | ||
// Escape RegExp chars | ||
pathValue = pathValue.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); | ||
pathValue = new RegExp("^" + pathValue + "$", "i"); | ||
} | ||
|
||
conditions[name] = pathValue; | ||
}); | ||
|
||
if (!isNew) { | ||
// Use conditions the user has with find*AndUpdate | ||
if (isQuery) { | ||
each(this._conditions, (value, key) => { | ||
conditions[key] = {$ne: value}; | ||
}); | ||
} else if (pathName !== "_id") { | ||
// if it's not new then it always has _id | ||
conditions._id = {$ne: this._id}; | ||
} else { | ||
// if is not new and is not query and the pathName is _id then is the same document no need to check anything | ||
return resolve(true); | ||
} | ||
} | ||
|
||
// Obtain the model depending on context | ||
// https://github.com/Automattic/mongoose/issues/3430 | ||
// https://github.com/Automattic/mongoose/issues/3589 | ||
let model; | ||
if (isQuery) { | ||
model = this.model; | ||
} else if (isSubdocument) { | ||
model = this.ownerDocument().model(this.ownerDocument().constructor.modelName); | ||
} else if (this.constructor.modelName) { | ||
// if the constructor has modelName then the constructor is the model | ||
model = this.constructor; | ||
} | ||
}); | ||
|
||
// Is this model a discriminator and the unique index is on the whole collection, | ||
// not just the instances of the discriminator? If so, use the base model to query. | ||
// https://github.com/Automattic/mongoose/issues/4965 | ||
if (model.baseModelName && indexOptions.partialFilterExpression === null) { | ||
model = model.db.model(model.baseModelName); | ||
} | ||
|
||
model.find(conditions).countDocuments((err, count) => { | ||
resolve(count === 0); | ||
}); | ||
}); | ||
}, | ||
pathMessage, | ||
type | ||
); | ||
} | ||
}); | ||
}); | ||
} | ||
}); | ||
}; |