summaryrefslogtreecommitdiffstats
path: root/node_modules/mongoose/lib/cast.js
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
commite06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch)
tree55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/mongoose/lib/cast.js
downloadwebsite_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip
api, login, auth
Diffstat (limited to 'node_modules/mongoose/lib/cast.js')
-rw-r--r--node_modules/mongoose/lib/cast.js364
1 files changed, 364 insertions, 0 deletions
diff --git a/node_modules/mongoose/lib/cast.js b/node_modules/mongoose/lib/cast.js
new file mode 100644
index 0000000..1c24bc7
--- /dev/null
+++ b/node_modules/mongoose/lib/cast.js
@@ -0,0 +1,364 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CastError = require('./error/cast');
+const StrictModeError = require('./error/strict');
+const Types = require('./schema/index');
+const castTextSearch = require('./schema/operators/text');
+const get = require('./helpers/get');
+const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
+const isOperator = require('./helpers/query/isOperator');
+const util = require('util');
+const isObject = require('./helpers/isObject');
+const isMongooseObject = require('./helpers/isMongooseObject');
+
+const ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon'];
+
+/**
+ * Handles internal casting for query filters.
+ *
+ * @param {Schema} schema
+ * @param {Object} obj Object to cast
+ * @param {Object} options the query options
+ * @param {Query} context passed to setters
+ * @api private
+ */
+module.exports = function cast(schema, obj, options, context) {
+ if (Array.isArray(obj)) {
+ throw new Error('Query filter must be an object, got an array ', util.inspect(obj));
+ }
+
+ if (obj == null) {
+ return obj;
+ }
+
+ // bson 1.x has the unfortunate tendency to remove filters that have a top-level
+ // `_bsontype` property. But we should still allow ObjectIds because
+ // `Collection#find()` has a special case to support `find(objectid)`.
+ // Should remove this when we upgrade to bson 4.x. See gh-8222, gh-8268
+ if (obj.hasOwnProperty('_bsontype') && obj._bsontype !== 'ObjectID') {
+ delete obj._bsontype;
+ }
+
+ if (schema != null && schema.discriminators != null && obj[schema.options.discriminatorKey] != null) {
+ schema = getSchemaDiscriminatorByValue(schema, obj[schema.options.discriminatorKey]) || schema;
+ }
+
+ const paths = Object.keys(obj);
+ let i = paths.length;
+ let _keys;
+ let any$conditionals;
+ let schematype;
+ let nested;
+ let path;
+ let type;
+ let val;
+
+ options = options || {};
+
+ while (i--) {
+ path = paths[i];
+ val = obj[path];
+
+ if (path === '$or' || path === '$nor' || path === '$and') {
+ if (!Array.isArray(val)) {
+ throw new CastError('Array', val, path);
+ }
+ for (let k = 0; k < val.length; ++k) {
+ if (val[k] == null || typeof val[k] !== 'object') {
+ throw new CastError('Object', val[k], path + '.' + k);
+ }
+ val[k] = cast(schema, val[k], options, context);
+ }
+ } else if (path === '$where') {
+ type = typeof val;
+
+ if (type !== 'string' && type !== 'function') {
+ throw new Error('Must have a string or function for $where');
+ }
+
+ if (type === 'function') {
+ obj[path] = val.toString();
+ }
+
+ continue;
+ } else if (path === '$elemMatch') {
+ val = cast(schema, val, options, context);
+ } else if (path === '$text') {
+ val = castTextSearch(val, path);
+ } else {
+ if (!schema) {
+ // no casting for Mixed types
+ continue;
+ }
+
+ schematype = schema.path(path);
+
+ // Check for embedded discriminator paths
+ if (!schematype) {
+ const split = path.split('.');
+ let j = split.length;
+ while (j--) {
+ const pathFirstHalf = split.slice(0, j).join('.');
+ const pathLastHalf = split.slice(j).join('.');
+ const _schematype = schema.path(pathFirstHalf);
+ const discriminatorKey = get(_schematype, 'schema.options.discriminatorKey');
+
+ // gh-6027: if we haven't found the schematype but this path is
+ // underneath an embedded discriminator and the embedded discriminator
+ // key is in the query, use the embedded discriminator schema
+ if (_schematype != null &&
+ get(_schematype, 'schema.discriminators') != null &&
+ discriminatorKey != null &&
+ pathLastHalf !== discriminatorKey) {
+ const discriminatorVal = get(obj, pathFirstHalf + '.' + discriminatorKey);
+ if (discriminatorVal != null) {
+ schematype = _schematype.schema.discriminators[discriminatorVal].
+ path(pathLastHalf);
+ }
+ }
+ }
+ }
+
+ if (!schematype) {
+ // Handle potential embedded array queries
+ const split = path.split('.');
+ let j = split.length;
+ let pathFirstHalf;
+ let pathLastHalf;
+ let remainingConds;
+
+ // Find the part of the var path that is a path of the Schema
+ while (j--) {
+ pathFirstHalf = split.slice(0, j).join('.');
+ schematype = schema.path(pathFirstHalf);
+ if (schematype) {
+ break;
+ }
+ }
+
+ // If a substring of the input path resolves to an actual real path...
+ if (schematype) {
+ // Apply the casting; similar code for $elemMatch in schema/array.js
+ if (schematype.caster && schematype.caster.schema) {
+ remainingConds = {};
+ pathLastHalf = split.slice(j).join('.');
+ remainingConds[pathLastHalf] = val;
+ obj[path] = cast(schematype.caster.schema, remainingConds, options, context)[pathLastHalf];
+ } else {
+ obj[path] = val;
+ }
+ continue;
+ }
+
+ if (isObject(val)) {
+ // handle geo schemas that use object notation
+ // { loc: { long: Number, lat: Number }
+
+ let geo = '';
+ if (val.$near) {
+ geo = '$near';
+ } else if (val.$nearSphere) {
+ geo = '$nearSphere';
+ } else if (val.$within) {
+ geo = '$within';
+ } else if (val.$geoIntersects) {
+ geo = '$geoIntersects';
+ } else if (val.$geoWithin) {
+ geo = '$geoWithin';
+ }
+
+ if (geo) {
+ const numbertype = new Types.Number('__QueryCasting__');
+ let value = val[geo];
+
+ if (val.$maxDistance != null) {
+ val.$maxDistance = numbertype.castForQueryWrapper({
+ val: val.$maxDistance,
+ context: context
+ });
+ }
+ if (val.$minDistance != null) {
+ val.$minDistance = numbertype.castForQueryWrapper({
+ val: val.$minDistance,
+ context: context
+ });
+ }
+
+ if (geo === '$within') {
+ const withinType = value.$center
+ || value.$centerSphere
+ || value.$box
+ || value.$polygon;
+
+ if (!withinType) {
+ throw new Error('Bad $within parameter: ' + JSON.stringify(val));
+ }
+
+ value = withinType;
+ } else if (geo === '$near' &&
+ typeof value.type === 'string' && Array.isArray(value.coordinates)) {
+ // geojson; cast the coordinates
+ value = value.coordinates;
+ } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') &&
+ value.$geometry && typeof value.$geometry.type === 'string' &&
+ Array.isArray(value.$geometry.coordinates)) {
+ if (value.$maxDistance != null) {
+ value.$maxDistance = numbertype.castForQueryWrapper({
+ val: value.$maxDistance,
+ context: context
+ });
+ }
+ if (value.$minDistance != null) {
+ value.$minDistance = numbertype.castForQueryWrapper({
+ val: value.$minDistance,
+ context: context
+ });
+ }
+ if (isMongooseObject(value.$geometry)) {
+ value.$geometry = value.$geometry.toObject({
+ transform: false,
+ virtuals: false
+ });
+ }
+ value = value.$geometry.coordinates;
+ } else if (geo === '$geoWithin') {
+ if (value.$geometry) {
+ if (isMongooseObject(value.$geometry)) {
+ value.$geometry = value.$geometry.toObject({ virtuals: false });
+ }
+ const geoWithinType = value.$geometry.type;
+ if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) {
+ throw new Error('Invalid geoJSON type for $geoWithin "' +
+ geoWithinType + '", must be "Polygon" or "MultiPolygon"');
+ }
+ value = value.$geometry.coordinates;
+ } else {
+ value = value.$box || value.$polygon || value.$center ||
+ value.$centerSphere;
+ if (isMongooseObject(value)) {
+ value = value.toObject({ virtuals: false });
+ }
+ }
+ }
+
+ _cast(value, numbertype, context);
+ continue;
+ }
+ }
+
+ if (schema.nested[path]) {
+ continue;
+ }
+ if (options.upsert && options.strict) {
+ if (options.strict === 'throw') {
+ throw new StrictModeError(path);
+ }
+ throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
+ 'schema, strict mode is `true`, and upsert is `true`.');
+ } else if (options.strictQuery === 'throw') {
+ throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
+ 'schema and strictQuery is \'throw\'.');
+ } else if (options.strictQuery) {
+ delete obj[path];
+ }
+ } else if (val == null) {
+ continue;
+ } else if (val.constructor.name === 'Object') {
+ any$conditionals = Object.keys(val).some(isOperator);
+
+ if (!any$conditionals) {
+ obj[path] = schematype.castForQueryWrapper({
+ val: val,
+ context: context
+ });
+ } else {
+ const ks = Object.keys(val);
+ let $cond;
+
+ let k = ks.length;
+
+ while (k--) {
+ $cond = ks[k];
+ nested = val[$cond];
+
+ if ($cond === '$not') {
+ if (nested && schematype && !schematype.caster) {
+ _keys = Object.keys(nested);
+ if (_keys.length && isOperator(_keys[0])) {
+ for (const key in nested) {
+ nested[key] = schematype.castForQueryWrapper({
+ $conditional: key,
+ val: nested[key],
+ context: context
+ });
+ }
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: context
+ });
+ }
+ continue;
+ }
+ cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: context
+ });
+ }
+ }
+ }
+ } else if (Array.isArray(val) && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) {
+ const casted = [];
+ const valuesArray = val;
+
+ for (const _val of valuesArray) {
+ casted.push(schematype.castForQueryWrapper({
+ val: _val,
+ context: context
+ }));
+ }
+
+ obj[path] = { $in: casted };
+ } else {
+ obj[path] = schematype.castForQueryWrapper({
+ val: val,
+ context: context
+ });
+ }
+ }
+ }
+
+ return obj;
+};
+
+function _cast(val, numbertype, context) {
+ if (Array.isArray(val)) {
+ val.forEach(function(item, i) {
+ if (Array.isArray(item) || isObject(item)) {
+ return _cast(item, numbertype, context);
+ }
+ val[i] = numbertype.castForQueryWrapper({ val: item, context: context });
+ });
+ } else {
+ const nearKeys = Object.keys(val);
+ let nearLen = nearKeys.length;
+ while (nearLen--) {
+ const nkey = nearKeys[nearLen];
+ const item = val[nkey];
+ if (Array.isArray(item) || isObject(item)) {
+ _cast(item, numbertype, context);
+ val[nkey] = item;
+ } else {
+ val[nkey] = numbertype.castForQuery({ val: item, context: context });
+ }
+ }
+ }
+} \ No newline at end of file