some progress

This commit is contained in:
Jonas_Jones 2023-03-30 20:40:42 +02:00
parent aea93a5527
commit e3c15bd288
1388 changed files with 306946 additions and 68323 deletions

View file

@ -0,0 +1,29 @@
'use strict';
const utils = require('../../utils');
function applyGlobalMaxTimeMS(options, model) {
applyGlobalOption(options, model, 'maxTimeMS');
}
function applyGlobalDiskUse(options, model) {
applyGlobalOption(options, model, 'allowDiskUse');
}
module.exports = {
applyGlobalMaxTimeMS,
applyGlobalDiskUse
};
function applyGlobalOption(options, model, optionName) {
if (utils.hasUserDefinedProperty(options, optionName)) {
return;
}
if (utils.hasUserDefinedProperty(model.db.options, optionName)) {
options[optionName] = model.db.options[optionName];
} else if (utils.hasUserDefinedProperty(model.base.options, optionName)) {
options[optionName] = model.base.options[optionName];
}
}

View file

@ -0,0 +1,54 @@
'use strict';
/*!
* ignore
*/
module.exports = applyQueryMiddleware;
const validOps = require('./validOps');
/*!
* ignore
*/
applyQueryMiddleware.middlewareFunctions = validOps.concat([
'validate'
]);
/**
* Apply query middleware
*
* @param {Query} Query constructor
* @param {Model} model
* @api private
*/
function applyQueryMiddleware(Query, model) {
const queryMiddleware = model.schema.s.hooks.filter(hook => {
const contexts = _getContexts(hook);
if (hook.name === 'validate') {
return !!contexts.query;
}
if (hook.name === 'deleteOne' || hook.name === 'updateOne') {
return !!contexts.query || Object.keys(contexts).length === 0;
}
if (hook.query != null || hook.document != null) {
return !!hook.query;
}
return true;
});
Query.prototype._queryMiddleware = queryMiddleware;
}
function _getContexts(hook) {
const ret = {};
if (hook.hasOwnProperty('query')) {
ret.query = hook.query;
}
if (hook.hasOwnProperty('document')) {
ret.document = hook.document;
}
return ret;
}

282
node_modules/mongoose/lib/helpers/query/cast$expr.js generated vendored Normal file
View file

@ -0,0 +1,282 @@
'use strict';
const CastError = require('../../error/cast');
const StrictModeError = require('../../error/strict');
const castNumber = require('../../cast/number');
const booleanComparison = new Set(['$and', '$or']);
const comparisonOperator = new Set(['$cmp', '$eq', '$lt', '$lte', '$gt', '$gte']);
const arithmeticOperatorArray = new Set([
// avoid casting '$add' or '$subtract', because expressions can be either number or date,
// and we don't have a good way of inferring which arguments should be numbers and which should
// be dates.
'$multiply',
'$divide',
'$log',
'$mod',
'$trunc',
'$avg',
'$max',
'$min',
'$stdDevPop',
'$stdDevSamp',
'$sum'
]);
const arithmeticOperatorNumber = new Set([
'$abs',
'$exp',
'$ceil',
'$floor',
'$ln',
'$log10',
'$round',
'$sqrt',
'$sin',
'$cos',
'$tan',
'$asin',
'$acos',
'$atan',
'$atan2',
'$asinh',
'$acosh',
'$atanh',
'$sinh',
'$cosh',
'$tanh',
'$degreesToRadians',
'$radiansToDegrees'
]);
const arrayElementOperators = new Set([
'$arrayElemAt',
'$first',
'$last'
]);
const dateOperators = new Set([
'$year',
'$month',
'$week',
'$dayOfMonth',
'$dayOfYear',
'$hour',
'$minute',
'$second',
'$isoDayOfWeek',
'$isoWeekYear',
'$isoWeek',
'$millisecond'
]);
const expressionOperator = new Set(['$not']);
module.exports = function cast$expr(val, schema, strictQuery) {
if (typeof val !== 'object' || val === null) {
throw new Error('`$expr` must be an object');
}
return _castExpression(val, schema, strictQuery);
};
function _castExpression(val, schema, strictQuery) {
// Preserve the value if it represents a path or if it's null
if (isPath(val) || val === null) {
return val;
}
if (val.$cond != null) {
if (Array.isArray(val.$cond)) {
val.$cond = val.$cond.map(expr => _castExpression(expr, schema, strictQuery));
} else {
val.$cond.if = _castExpression(val.$cond.if, schema, strictQuery);
val.$cond.then = _castExpression(val.$cond.then, schema, strictQuery);
val.$cond.else = _castExpression(val.$cond.else, schema, strictQuery);
}
} else if (val.$ifNull != null) {
val.$ifNull.map(v => _castExpression(v, schema, strictQuery));
} else if (val.$switch != null) {
val.branches.map(v => _castExpression(v, schema, strictQuery));
val.default = _castExpression(val.default, schema, strictQuery);
}
const keys = Object.keys(val);
for (const key of keys) {
if (booleanComparison.has(key)) {
val[key] = val[key].map(v => _castExpression(v, schema, strictQuery));
} else if (comparisonOperator.has(key)) {
val[key] = castComparison(val[key], schema, strictQuery);
} else if (arithmeticOperatorArray.has(key)) {
val[key] = castArithmetic(val[key], schema, strictQuery);
} else if (arithmeticOperatorNumber.has(key)) {
val[key] = castNumberOperator(val[key], schema, strictQuery);
} else if (expressionOperator.has(key)) {
val[key] = _castExpression(val[key], schema, strictQuery);
}
}
if (val.$in) {
val.$in = castIn(val.$in, schema, strictQuery);
}
if (val.$size) {
val.$size = castNumberOperator(val.$size, schema, strictQuery);
}
_omitUndefined(val);
return val;
}
function _omitUndefined(val) {
const keys = Object.keys(val);
for (let i = 0, len = keys.length; i < len; ++i) {
(val[keys[i]] === void 0) && delete val[keys[i]];
}
}
// { $op: <number> }
function castNumberOperator(val) {
if (!isLiteral(val)) {
return val;
}
try {
return castNumber(val);
} catch (err) {
throw new CastError('Number', val);
}
}
function castIn(val, schema, strictQuery) {
const path = val[1];
if (!isPath(path)) {
return val;
}
const search = val[0];
const schematype = schema.path(path.slice(1));
if (schematype === null) {
if (strictQuery === false) {
return val;
} else if (strictQuery === 'throw') {
throw new StrictModeError('$in');
}
return void 0;
}
if (!schematype.$isMongooseArray) {
throw new Error('Path must be an array for $in');
}
return [
schematype.$isMongooseDocumentArray ? schematype.$embeddedSchemaType.cast(search) : schematype.caster.cast(search),
path
];
}
// { $op: [<number>, <number>] }
function castArithmetic(val) {
if (!Array.isArray(val)) {
if (!isLiteral(val)) {
return val;
}
try {
return castNumber(val);
} catch (err) {
throw new CastError('Number', val);
}
}
return val.map(v => {
if (!isLiteral(v)) {
return v;
}
try {
return castNumber(v);
} catch (err) {
throw new CastError('Number', v);
}
});
}
// { $op: [expression, expression] }
function castComparison(val, schema, strictQuery) {
if (!Array.isArray(val) || val.length !== 2) {
throw new Error('Comparison operator must be an array of length 2');
}
val[0] = _castExpression(val[0], schema, strictQuery);
const lhs = val[0];
if (isLiteral(val[1])) {
let path = null;
let schematype = null;
let caster = null;
if (isPath(lhs)) {
path = lhs.slice(1);
schematype = schema.path(path);
} else if (typeof lhs === 'object' && lhs != null) {
for (const key of Object.keys(lhs)) {
if (dateOperators.has(key) && isPath(lhs[key])) {
path = lhs[key].slice(1) + '.' + key;
caster = castNumber;
} else if (arrayElementOperators.has(key) && isPath(lhs[key])) {
path = lhs[key].slice(1) + '.' + key;
schematype = schema.path(lhs[key].slice(1));
if (schematype != null) {
if (schematype.$isMongooseDocumentArray) {
schematype = schematype.$embeddedSchemaType;
} else if (schematype.$isMongooseArray) {
schematype = schematype.caster;
}
}
}
}
}
const is$literal = typeof val[1] === 'object' && val[1] != null && val[1].$literal != null;
if (schematype != null) {
if (is$literal) {
val[1] = { $literal: schematype.cast(val[1].$literal) };
} else {
val[1] = schematype.cast(val[1]);
}
} else if (caster != null) {
if (is$literal) {
try {
val[1] = { $literal: caster(val[1].$literal) };
} catch (err) {
throw new CastError(caster.name.replace(/^cast/, ''), val[1], path + '.$literal');
}
} else {
try {
val[1] = caster(val[1]);
} catch (err) {
throw new CastError(caster.name.replace(/^cast/, ''), val[1], path);
}
}
} else if (path != null && strictQuery === true) {
return void 0;
} else if (path != null && strictQuery === 'throw') {
throw new StrictModeError(path);
}
} else {
val[1] = _castExpression(val[1]);
}
return val;
}
function isPath(val) {
return typeof val === 'string' && val[0] === '$';
}
function isLiteral(val) {
if (typeof val === 'string' && val[0] === '$') {
return false;
}
if (typeof val === 'object' && val !== null && Object.keys(val).find(key => key[0] === '$')) {
// The `$literal` expression can make an object a literal
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/literal/#mongodb-expression-exp.-literal
return val.$literal != null;
}
return true;
}

View file

@ -0,0 +1,55 @@
'use strict';
const isOperator = require('./isOperator');
module.exports = function castFilterPath(query, schematype, val) {
const ctx = query;
const any$conditionals = Object.keys(val).some(isOperator);
if (!any$conditionals) {
return schematype.castForQuery(
null,
val,
ctx
);
}
const ks = Object.keys(val);
let k = ks.length;
while (k--) {
const $cond = ks[k];
const nested = val[$cond];
if ($cond === '$not') {
if (nested && schematype && !schematype.caster) {
const _keys = Object.keys(nested);
if (_keys.length && isOperator(_keys[0])) {
for (const key of Object.keys(nested)) {
nested[key] = schematype.castForQuery(
key,
nested[key],
ctx
);
}
} else {
val[$cond] = schematype.castForQuery(
$cond,
nested,
ctx
);
}
continue;
}
} else {
val[$cond] = schematype.castForQuery(
$cond,
nested,
ctx
);
}
}
return val;
};

565
node_modules/mongoose/lib/helpers/query/castUpdate.js generated vendored Normal file
View file

@ -0,0 +1,565 @@
'use strict';
const CastError = require('../../error/cast');
const MongooseError = require('../../error/mongooseError');
const StrictModeError = require('../../error/strict');
const ValidationError = require('../../error/validation');
const castNumber = require('../../cast/number');
const cast = require('../../cast');
const getConstructorName = require('../getConstructorName');
const getEmbeddedDiscriminatorPath = require('./getEmbeddedDiscriminatorPath');
const handleImmutable = require('./handleImmutable');
const moveImmutableProperties = require('../update/moveImmutableProperties');
const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
const setDottedPath = require('../path/setDottedPath');
const utils = require('../../utils');
/**
* Casts an update op based on the given schema
*
* @param {Schema} schema
* @param {Object} obj
* @param {Object} [options]
* @param {Boolean} [options.overwrite] defaults to false
* @param {Boolean|String} [options.strict] defaults to true
* @param {Query} context passed to setters
* @return {Boolean} true iff the update is non-empty
* @api private
*/
module.exports = function castUpdate(schema, obj, options, context, filter) {
if (obj == null) {
return undefined;
}
options = options || {};
// Update pipeline
if (Array.isArray(obj)) {
const len = obj.length;
for (let i = 0; i < len; ++i) {
const ops = Object.keys(obj[i]);
for (const op of ops) {
obj[i][op] = castPipelineOperator(op, obj[i][op]);
}
}
return obj;
}
if (options.upsert && !options.overwrite) {
moveImmutableProperties(schema, obj, context);
}
const ops = Object.keys(obj);
let i = ops.length;
const ret = {};
let val;
let hasDollarKey = false;
const overwrite = options.overwrite;
filter = filter || {};
while (i--) {
const op = ops[i];
// if overwrite is set, don't do any of the special $set stuff
if (op[0] !== '$' && !overwrite) {
// fix up $set sugar
if (!ret.$set) {
if (obj.$set) {
ret.$set = obj.$set;
} else {
ret.$set = {};
}
}
ret.$set[op] = obj[op];
ops.splice(i, 1);
if (!~ops.indexOf('$set')) ops.push('$set');
} else if (op === '$set') {
if (!ret.$set) {
ret[op] = obj[op];
}
} else {
ret[op] = obj[op];
}
}
// cast each value
i = ops.length;
while (i--) {
const op = ops[i];
val = ret[op];
hasDollarKey = hasDollarKey || op.startsWith('$');
if (val &&
typeof val === 'object' &&
!Buffer.isBuffer(val) &&
(!overwrite || hasDollarKey)) {
walkUpdatePath(schema, val, op, options, context, filter);
} else if (overwrite && ret && typeof ret === 'object') {
walkUpdatePath(schema, ret, '$set', options, context, filter);
} else {
const msg = 'Invalid atomic update value for ' + op + '. '
+ 'Expected an object, received ' + typeof val;
throw new Error(msg);
}
if (op.startsWith('$') && utils.isEmptyObject(val)) {
delete ret[op];
}
}
if (Object.keys(ret).length === 0 &&
options.upsert &&
Object.keys(filter).length > 0) {
// Trick the driver into allowing empty upserts to work around
// https://github.com/mongodb/node-mongodb-native/pull/2490
return { $setOnInsert: filter };
}
return ret;
};
/*!
* ignore
*/
function castPipelineOperator(op, val) {
if (op === '$unset') {
if (typeof val !== 'string' && (!Array.isArray(val) || val.find(v => typeof v !== 'string'))) {
throw new MongooseError('Invalid $unset in pipeline, must be ' +
' a string or an array of strings');
}
return val;
}
if (op === '$project') {
if (val == null || typeof val !== 'object') {
throw new MongooseError('Invalid $project in pipeline, must be an object');
}
return val;
}
if (op === '$addFields' || op === '$set') {
if (val == null || typeof val !== 'object') {
throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
}
return val;
} else if (op === '$replaceRoot' || op === '$replaceWith') {
if (val == null || typeof val !== 'object') {
throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
}
return val;
}
throw new MongooseError('Invalid update pipeline operator: "' + op + '"');
}
/**
* Walk each path of obj and cast its values
* according to its schema.
*
* @param {Schema} schema
* @param {Object} obj part of a query
* @param {String} op the atomic operator ($pull, $set, etc)
* @param {Object} [options]
* @param {Boolean|String} [options.strict]
* @param {Query} context
* @param {Object} filter
* @param {String} pref path prefix (internal only)
* @return {Bool} true if this path has keys to update
* @api private
*/
function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
const strict = options.strict;
const prefix = pref ? pref + '.' : '';
const keys = Object.keys(obj);
let i = keys.length;
let hasKeys = false;
let schematype;
let key;
let val;
let aggregatedError = null;
const strictMode = strict != null ? strict : schema.options.strict;
while (i--) {
key = keys[i];
val = obj[key];
// `$pull` is special because we need to cast the RHS as a query, not as
// an update.
if (op === '$pull') {
schematype = schema._getSchema(prefix + key);
if (schematype != null && schematype.schema != null) {
obj[key] = cast(schematype.schema, obj[key], options, context);
hasKeys = true;
continue;
}
}
const discriminatorKey = (prefix ? prefix + key : key);
if (
schema.discriminatorMapping != null &&
discriminatorKey === schema.options.discriminatorKey &&
schema.discriminatorMapping.value !== obj[key] &&
!options.overwriteDiscriminatorKey
) {
if (strictMode === 'throw') {
const err = new Error('Can\'t modify discriminator key "' + discriminatorKey + '" on discriminator model');
aggregatedError = _appendError(err, context, discriminatorKey, aggregatedError);
continue;
} else if (strictMode) {
delete obj[key];
continue;
}
}
if (getConstructorName(val) === 'Object') {
// watch for embedded doc schemas
schematype = schema._getSchema(prefix + key);
if (schematype == null) {
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, prefix + key, options);
if (_res.schematype != null) {
schematype = _res.schematype;
}
}
if (op !== '$setOnInsert' &&
!options.overwrite &&
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
continue;
}
if (schematype && schematype.caster && op in castOps) {
// embedded doc schema
if ('$each' in val) {
hasKeys = true;
try {
obj[key] = {
$each: castUpdateVal(schematype, val.$each, op, key, context, prefix + key)
};
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}
if (val.$slice != null) {
obj[key].$slice = val.$slice | 0;
}
if (val.$sort) {
obj[key].$sort = val.$sort;
}
if (val.$position != null) {
obj[key].$position = castNumber(val.$position);
}
} else {
if (schematype != null && schematype.$isSingleNested) {
const _strict = strict == null ? schematype.schema.options.strict : strict;
try {
obj[key] = schematype.castForQuery(null, val, context, { strict: _strict });
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}
} else {
try {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}
}
if (obj[key] === void 0) {
delete obj[key];
continue;
}
hasKeys = true;
}
} else if ((op === '$currentDate') || (op in castOps && schematype)) {
// $currentDate can take an object
try {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}
if (obj[key] === void 0) {
delete obj[key];
continue;
}
hasKeys = true;
} else {
const pathToCheck = (prefix + key);
const v = schema._getPathType(pathToCheck);
let _strict = strict;
if (v && v.schema && _strict == null) {
_strict = v.schema.options.strict;
}
if (v.pathType === 'undefined') {
if (_strict === 'throw') {
throw new StrictModeError(pathToCheck);
} else if (_strict) {
delete obj[key];
continue;
}
}
// gh-2314
// we should be able to set a schema-less field
// to an empty object literal
hasKeys |= walkUpdatePath(schema, val, op, options, context, filter, prefix + key) ||
(utils.isObject(val) && Object.keys(val).length === 0);
}
} else {
const checkPath = (key === '$each' || key === '$or' || key === '$and' || key === '$in') ?
pref : prefix + key;
schematype = schema._getSchema(checkPath);
// You can use `$setOnInsert` with immutable keys
if (op !== '$setOnInsert' &&
!options.overwrite &&
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
continue;
}
let pathDetails = schema._getPathType(checkPath);
// If no schema type, check for embedded discriminators because the
// filter or update may imply an embedded discriminator type. See #8378
if (schematype == null) {
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath, options);
if (_res.schematype != null) {
schematype = _res.schematype;
pathDetails = _res.type;
}
}
let isStrict = strict;
if (pathDetails && pathDetails.schema && strict == null) {
isStrict = pathDetails.schema.options.strict;
}
const skip = isStrict &&
!schematype &&
!/real|nested/.test(pathDetails.pathType);
if (skip) {
// Even if strict is `throw`, avoid throwing an error because of
// virtuals because of #6731
if (isStrict === 'throw' && schema.virtuals[checkPath] == null) {
throw new StrictModeError(prefix + key);
} else {
delete obj[key];
}
} else {
// gh-1845 temporary fix: ignore $rename. See gh-3027 for tracking
// improving this.
if (op === '$rename') {
hasKeys = true;
continue;
}
try {
if (prefix.length === 0 || key.indexOf('.') === -1) {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} else {
// Setting a nested dotted path that's in the schema. We don't allow paths with '.' in
// a schema, so replace the dotted path with a nested object to avoid ending up with
// dotted properties in the updated object. See (gh-10200)
setDottedPath(obj, key, castUpdateVal(schematype, val, op, key, context, prefix + key));
delete obj[key];
}
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}
if (Array.isArray(obj[key]) && (op === '$addToSet' || op === '$push') && key !== '$each') {
if (schematype &&
schematype.caster &&
!schematype.caster.$isMongooseArray &&
!schematype.caster[schemaMixedSymbol]) {
obj[key] = { $each: obj[key] };
}
}
if (obj[key] === void 0) {
delete obj[key];
continue;
}
hasKeys = true;
}
}
}
if (aggregatedError != null) {
throw aggregatedError;
}
return hasKeys;
}
/*!
* ignore
*/
function _appendError(error, query, key, aggregatedError) {
if (typeof query !== 'object' || !query.options.multipleCastError) {
throw error;
}
aggregatedError = aggregatedError || new ValidationError();
aggregatedError.addError(key, error);
return aggregatedError;
}
/**
* These operators should be cast to numbers instead
* of their path schema type.
* @api private
*/
const numberOps = {
$pop: 1,
$inc: 1
};
/**
* These ops require no casting because the RHS doesn't do anything.
* @api private
*/
const noCastOps = {
$unset: 1
};
/**
* These operators require casting docs
* to real Documents for Update operations.
* @api private
*/
const castOps = {
$push: 1,
$addToSet: 1,
$set: 1,
$setOnInsert: 1
};
/*!
* ignore
*/
const overwriteOps = {
$set: 1,
$setOnInsert: 1
};
/**
* Casts `val` according to `schema` and atomic `op`.
*
* @param {SchemaType} schema
* @param {Object} val
* @param {String} op the atomic operator ($pull, $set, etc)
* @param {String} $conditional
* @param {Query} context
* @param {String} path
* @api private
*/
function castUpdateVal(schema, val, op, $conditional, context, path) {
if (!schema) {
// non-existing schema path
if (op in numberOps) {
try {
return castNumber(val);
} catch (err) {
throw new CastError('number', val, path);
}
}
return val;
}
// console.log('CastUpdateVal', path, op, val, schema);
const cond = schema.caster && op in castOps &&
(utils.isObject(val) || Array.isArray(val));
if (cond && !overwriteOps[op]) {
// Cast values for ops that add data to MongoDB.
// Ensures embedded documents get ObjectIds etc.
let schemaArrayDepth = 0;
let cur = schema;
while (cur.$isMongooseArray) {
++schemaArrayDepth;
cur = cur.caster;
}
let arrayDepth = 0;
let _val = val;
while (Array.isArray(_val)) {
++arrayDepth;
_val = _val[0];
}
const additionalNesting = schemaArrayDepth - arrayDepth;
while (arrayDepth < schemaArrayDepth) {
val = [val];
++arrayDepth;
}
let tmp = schema.applySetters(Array.isArray(val) ? val : [val], context);
for (let i = 0; i < additionalNesting; ++i) {
tmp = tmp[0];
}
return tmp;
}
if (op in noCastOps) {
return val;
}
if (op in numberOps) {
// Null and undefined not allowed for $pop, $inc
if (val == null) {
throw new CastError('number', val, schema.path);
}
if (op === '$inc') {
// Support `$inc` with long, int32, etc. (gh-4283)
return schema.castForQuery(
null,
val,
context
);
}
try {
return castNumber(val);
} catch (error) {
throw new CastError('number', val, schema.path);
}
}
if (op === '$currentDate') {
if (typeof val === 'object') {
return { $type: val.$type };
}
return Boolean(val);
}
if (/^\$/.test($conditional)) {
return schema.castForQuery(
$conditional,
val,
context
);
}
if (overwriteOps[op]) {
const skipQueryCastForUpdate = val != null && schema.$isMongooseArray && schema.$fullPath != null && !schema.$fullPath.match(/\d+$/);
const applySetters = schema[schemaMixedSymbol] != null;
if (skipQueryCastForUpdate || applySetters) {
return schema.applySetters(val, context);
}
return schema.castForQuery(
null,
val,
context
);
}
return schema.castForQuery(null, val, context);
}

View file

@ -0,0 +1,36 @@
'use strict';
const helpers = require('../../queryhelpers');
module.exports = completeMany;
/**
* Given a model and an array of docs, hydrates all the docs to be instances
* of the model. Used to initialize docs returned from the db from `find()`
*
* @param {Model} model
* @param {Array} docs
* @param {Object} fields the projection used, including `select` from schemas
* @param {Object} userProvidedFields the user-specified projection
* @param {Object} [opts]
* @param {Array} [opts.populated]
* @param {ClientSession} [opts.session]
* @param {Function} callback
* @api private
*/
async function completeMany(model, docs, fields, userProvidedFields, opts) {
return Promise.all(docs.map(doc => new Promise((resolve, reject) => {
const rawDoc = doc;
doc = helpers.createModel(model, doc, fields, userProvidedFields);
if (opts.session != null) {
doc.$session(opts.session);
}
doc.$init(rawDoc, opts, (err) => {
if (err != null) {
return reject(err);
}
resolve(doc);
});
})));
}

View file

@ -0,0 +1,90 @@
'use strict';
const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
const get = require('../get');
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
const updatedPathsByArrayFilter = require('../update/updatedPathsByArrayFilter');
/**
* Like `schema.path()`, except with a document, because impossible to
* determine path type without knowing the embedded discriminator key.
* @param {Schema} schema
* @param {Object} [update]
* @param {Object} [filter]
* @param {String} path
* @param {Object} [options]
* @api private
*/
module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path, options) {
const parts = path.split('.');
let schematype = null;
let type = 'adhocOrUndefined';
filter = filter || {};
update = update || {};
const arrayFilters = options != null && Array.isArray(options.arrayFilters) ?
options.arrayFilters : [];
const updatedPathsByFilter = updatedPathsByArrayFilter(update);
for (let i = 0; i < parts.length; ++i) {
const subpath = cleanPositionalOperators(parts.slice(0, i + 1).join('.'));
schematype = schema.path(subpath);
if (schematype == null) {
continue;
}
type = schema.pathType(subpath);
if ((schematype.$isSingleNested || schematype.$isMongooseDocumentArrayElement) &&
schematype.schema.discriminators != null) {
const key = get(schematype, 'schema.options.discriminatorKey');
const discriminatorValuePath = subpath + '.' + key;
const discriminatorFilterPath =
discriminatorValuePath.replace(/\.\d+\./, '.');
let discriminatorKey = null;
if (discriminatorValuePath in filter) {
discriminatorKey = filter[discriminatorValuePath];
}
if (discriminatorFilterPath in filter) {
discriminatorKey = filter[discriminatorFilterPath];
}
const wrapperPath = subpath.replace(/\.\d+$/, '');
if (schematype.$isMongooseDocumentArrayElement &&
get(filter[wrapperPath], '$elemMatch.' + key) != null) {
discriminatorKey = filter[wrapperPath].$elemMatch[key];
}
if (discriminatorValuePath in update) {
discriminatorKey = update[discriminatorValuePath];
}
for (const filterKey of Object.keys(updatedPathsByFilter)) {
const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
const arrayFilterKey = filterKey + '.' + key;
if (schemaKey === discriminatorFilterPath) {
const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey));
if (filter != null) {
discriminatorKey = filter[arrayFilterKey];
}
}
}
if (discriminatorKey == null) {
continue;
}
const discriminatorSchema = getDiscriminatorByValue(schematype.caster.discriminators, discriminatorKey).schema;
const rest = parts.slice(i + 1).join('.');
schematype = discriminatorSchema.path(rest);
if (schematype != null) {
type = discriminatorSchema._getPathType(rest);
break;
}
}
}
return { type: type, schematype: schematype };
};

View file

@ -0,0 +1,28 @@
'use strict';
const StrictModeError = require('../../error/strict');
module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, ctx) {
if (schematype == null || !schematype.options || !schematype.options.immutable) {
return false;
}
let immutable = schematype.options.immutable;
if (typeof immutable === 'function') {
immutable = immutable.call(ctx, ctx);
}
if (!immutable) {
return false;
}
if (strict === false) {
return false;
}
if (strict === 'throw') {
throw new StrictModeError(null,
`Field ${fullPath} is immutable and strict = 'throw'`);
}
delete obj[key];
return true;
};

View file

@ -0,0 +1,23 @@
'use strict';
module.exports = function handleReadPreferenceAliases(pref) {
switch (pref) {
case 'p':
pref = 'primary';
break;
case 'pp':
pref = 'primaryPreferred';
break;
case 's':
pref = 'secondary';
break;
case 'sp':
pref = 'secondaryPreferred';
break;
case 'n':
pref = 'nearest';
break;
}
return pref;
};

View file

@ -0,0 +1,23 @@
'use strict';
/*!
* ignore
*/
module.exports = function hasDollarKeys(obj) {
if (typeof obj !== 'object' || obj === null) {
return false;
}
const keys = Object.keys(obj);
const len = keys.length;
for (let i = 0; i < len; ++i) {
if (keys[i][0] === '$') {
return true;
}
}
return false;
};

14
node_modules/mongoose/lib/helpers/query/isOperator.js generated vendored Normal file
View file

@ -0,0 +1,14 @@
'use strict';
const specialKeys = new Set([
'$ref',
'$id',
'$db'
]);
module.exports = function isOperator(path) {
return (
path[0] === '$' &&
!specialKeys.has(path)
);
};

View file

@ -0,0 +1,38 @@
'use strict';
const hasDollarKeys = require('./hasDollarKeys');
const { trustedSymbol } = require('./trusted');
module.exports = function sanitizeFilter(filter) {
if (filter == null || typeof filter !== 'object') {
return filter;
}
if (Array.isArray(filter)) {
for (const subfilter of filter) {
sanitizeFilter(subfilter);
}
return filter;
}
const filterKeys = Object.keys(filter);
for (const key of filterKeys) {
const value = filter[key];
if (value != null && value[trustedSymbol]) {
continue;
}
if (key === '$and' || key === '$or') {
sanitizeFilter(value);
continue;
}
if (hasDollarKeys(value)) {
const keys = Object.keys(value);
if (keys.length === 1 && keys[0] === '$eq') {
continue;
}
filter[key] = { $eq: filter[key] };
}
}
return filter;
};

View file

@ -0,0 +1,14 @@
'use strict';
module.exports = function sanitizeProjection(projection) {
if (projection == null) {
return;
}
const keys = Object.keys(projection);
for (let i = 0; i < keys.length; ++i) {
if (typeof projection[keys[i]] === 'string') {
projection[keys[i]] = 1;
}
}
};

View file

@ -0,0 +1,49 @@
'use strict';
const isExclusive = require('../projection/isExclusive');
const isInclusive = require('../projection/isInclusive');
/*!
* ignore
*/
module.exports = function selectPopulatedFields(fields, userProvidedFields, populateOptions) {
if (populateOptions == null) {
return;
}
const paths = Object.keys(populateOptions);
userProvidedFields = userProvidedFields || {};
if (isInclusive(fields)) {
for (const path of paths) {
if (!isPathInFields(userProvidedFields, path)) {
fields[path] = 1;
} else if (userProvidedFields[path] === 0) {
delete fields[path];
}
}
} else if (isExclusive(fields)) {
for (const path of paths) {
if (userProvidedFields[path] == null) {
delete fields[path];
}
}
}
};
/*!
* ignore
*/
function isPathInFields(userProvidedFields, path) {
const pieces = path.split('.');
const len = pieces.length;
let cur = pieces[0];
for (let i = 1; i < len; ++i) {
if (userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null) {
return true;
}
cur += '.' + pieces[i];
}
return userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null;
}

13
node_modules/mongoose/lib/helpers/query/trusted.js generated vendored Normal file
View file

@ -0,0 +1,13 @@
'use strict';
const trustedSymbol = Symbol('mongoose#trustedSymbol');
exports.trustedSymbol = trustedSymbol;
exports.trusted = function trusted(obj) {
if (obj == null || typeof obj !== 'object') {
return obj;
}
obj[trustedSymbol] = true;
return obj;
};

22
node_modules/mongoose/lib/helpers/query/validOps.js generated vendored Normal file
View file

@ -0,0 +1,22 @@
'use strict';
module.exports = Object.freeze([
// Read
'count',
'countDocuments',
'distinct',
'estimatedDocumentCount',
'find',
'findOne',
// Update
'findOneAndReplace',
'findOneAndUpdate',
'replaceOne',
'updateMany',
'updateOne',
// Delete
'deleteMany',
'deleteOne',
'findOneAndDelete',
'findOneAndRemove'
]);