diff options
author | 2020-11-16 00:10:28 +0100 | |
---|---|---|
committer | 2020-11-16 00:10:28 +0100 | |
commit | e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch) | |
tree | 55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/mongoose/lib/helpers/model | |
download | website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2 website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip |
api, login, auth
Diffstat (limited to 'node_modules/mongoose/lib/helpers/model')
6 files changed, 703 insertions, 0 deletions
diff --git a/node_modules/mongoose/lib/helpers/model/applyHooks.js b/node_modules/mongoose/lib/helpers/model/applyHooks.js new file mode 100644 index 0000000..9570a36 --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/applyHooks.js @@ -0,0 +1,135 @@ +'use strict'; + +const symbols = require('../../schema/symbols'); +const promiseOrCallback = require('../promiseOrCallback'); + +/*! + * ignore + */ + +module.exports = applyHooks; + +/*! + * ignore + */ + +applyHooks.middlewareFunctions = [ + 'deleteOne', + 'save', + 'validate', + 'remove', + 'updateOne', + 'init' +]; + +/*! + * Register hooks for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +function applyHooks(model, schema, options) { + options = options || {}; + + const kareemOptions = { + useErrorHandlers: true, + numCallbackParams: 1, + nullResultByDefault: true, + contextParameter: true + }; + const objToDecorate = options.decorateDoc ? model : model.prototype; + + model.$appliedHooks = true; + for (const key of Object.keys(schema.paths)) { + const type = schema.paths[key]; + let childModel = null; + if (type.$isSingleNested) { + childModel = type.caster; + } else if (type.$isMongooseDocumentArray) { + childModel = type.Constructor; + } else { + continue; + } + + if (childModel.$appliedHooks) { + continue; + } + + applyHooks(childModel, type.schema, options); + if (childModel.discriminators != null) { + const keys = Object.keys(childModel.discriminators); + for (const key of keys) { + applyHooks(childModel.discriminators[key], + childModel.discriminators[key].schema, options); + } + } + } + + // Built-in hooks rely on hooking internal functions in order to support + // promises and make it so that `doc.save.toString()` provides meaningful + // information. + + const middleware = schema.s.hooks. + filter(hook => { + if (hook.name === 'updateOne' || hook.name === 'deleteOne') { + return !!hook['document']; + } + if (hook.name === 'remove' || hook.name === 'init') { + return hook['document'] == null || !!hook['document']; + } + return true; + }). + filter(hook => { + // If user has overwritten the method, don't apply built-in middleware + if (schema.methods[hook.name]) { + return !hook.fn[symbols.builtInMiddleware]; + } + + return true; + }); + + model._middleware = middleware; + + objToDecorate.$__originalValidate = objToDecorate.$__originalValidate || objToDecorate.$__validate; + + for (const method of ['save', 'validate', 'remove', 'deleteOne']) { + const toWrap = method === 'validate' ? '$__originalValidate' : `$__${method}`; + const wrapped = middleware. + createWrapper(method, objToDecorate[toWrap], null, kareemOptions); + objToDecorate[`$__${method}`] = wrapped; + } + objToDecorate.$__init = middleware. + createWrapperSync('init', objToDecorate.$__init, null, kareemOptions); + + // Support hooks for custom methods + const customMethods = Object.keys(schema.methods); + const customMethodOptions = Object.assign({}, kareemOptions, { + // Only use `checkForPromise` for custom methods, because mongoose + // query thunks are not as consistent as I would like about returning + // a nullish value rather than the query. If a query thunk returns + // a query, `checkForPromise` causes infinite recursion + checkForPromise: true + }); + for (const method of customMethods) { + if (!middleware.hasHooks(method)) { + // Don't wrap if there are no hooks for the custom method to avoid + // surprises. Also, `createWrapper()` enforces consistent async, + // so wrapping a sync method would break it. + continue; + } + const originalMethod = objToDecorate[method]; + objToDecorate[method] = function() { + const args = Array.prototype.slice.call(arguments); + const cb = args.slice(-1).pop(); + const argsWithoutCallback = typeof cb === 'function' ? + args.slice(0, args.length - 1) : args; + return promiseOrCallback(cb, callback => { + return this[`$__${method}`].apply(this, + argsWithoutCallback.concat([callback])); + }, model.events); + }; + objToDecorate[`$__${method}`] = middleware. + createWrapper(method, originalMethod, null, customMethodOptions); + } +}
\ No newline at end of file diff --git a/node_modules/mongoose/lib/helpers/model/applyMethods.js b/node_modules/mongoose/lib/helpers/model/applyMethods.js new file mode 100644 index 0000000..912f3aa --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/applyMethods.js @@ -0,0 +1,56 @@ +'use strict'; + +const get = require('../get'); + +/*! + * Register methods for this model + * + * @param {Model} model + * @param {Schema} schema + */ + +module.exports = function applyMethods(model, schema) { + function apply(method, schema) { + Object.defineProperty(model.prototype, method, { + get: function() { + const h = {}; + for (const k in schema.methods[method]) { + h[k] = schema.methods[method][k].bind(this); + } + return h; + }, + configurable: true + }); + } + for (const method of Object.keys(schema.methods)) { + const fn = schema.methods[method]; + if (schema.tree.hasOwnProperty(method)) { + throw new Error('You have a method and a property in your schema both ' + + 'named "' + method + '"'); + } + if (schema.reserved[method] && + !get(schema, `methodOptions.${method}.suppressWarning`, false)) { + console.warn(`mongoose: the method name "${method}" is used by mongoose ` + + 'internally, overwriting it may cause bugs. If you\'re sure you know ' + + 'what you\'re doing, you can suppress this error by using ' + + `\`schema.method('${method}', fn, { suppressWarning: true })\`.`); + } + if (typeof fn === 'function') { + model.prototype[method] = fn; + } else { + apply(method, schema); + } + } + + // Recursively call `applyMethods()` on child schemas + model.$appliedMethods = true; + for (const key of Object.keys(schema.paths)) { + const type = schema.paths[key]; + if (type.$isSingleNested && !type.caster.$appliedMethods) { + applyMethods(type.caster, type.schema); + } + if (type.$isMongooseDocumentArray && !type.Constructor.$appliedMethods) { + applyMethods(type.Constructor, type.schema); + } + } +}; diff --git a/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js b/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js new file mode 100644 index 0000000..219e289 --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js @@ -0,0 +1,71 @@ +'use strict'; + +const middlewareFunctions = require('../query/applyQueryMiddleware').middlewareFunctions; +const promiseOrCallback = require('../promiseOrCallback'); + +module.exports = function applyStaticHooks(model, hooks, statics) { + const kareemOptions = { + useErrorHandlers: true, + numCallbackParams: 1 + }; + + hooks = hooks.filter(hook => { + // If the custom static overwrites an existing query middleware, don't apply + // middleware to it by default. This avoids a potential backwards breaking + // change with plugins like `mongoose-delete` that use statics to overwrite + // built-in Mongoose functions. + if (middlewareFunctions.indexOf(hook.name) !== -1) { + return !!hook.model; + } + return hook.model !== false; + }); + + model.$__insertMany = hooks.createWrapper('insertMany', + model.$__insertMany, model, kareemOptions); + + for (const key of Object.keys(statics)) { + if (hooks.hasHooks(key)) { + const original = model[key]; + + model[key] = function() { + const numArgs = arguments.length; + const lastArg = numArgs > 0 ? arguments[numArgs - 1] : null; + const cb = typeof lastArg === 'function' ? lastArg : null; + const args = Array.prototype.slice. + call(arguments, 0, cb == null ? numArgs : numArgs - 1); + // Special case: can't use `Kareem#wrap()` because it doesn't currently + // support wrapped functions that return a promise. + return promiseOrCallback(cb, callback => { + hooks.execPre(key, model, args, function(err) { + if (err != null) { + return callback(err); + } + + let postCalled = 0; + const ret = original.apply(model, args.concat(post)); + if (ret != null && typeof ret.then === 'function') { + ret.then(res => post(null, res), err => post(err)); + } + + function post(error, res) { + if (postCalled++ > 0) { + return; + } + + if (error != null) { + return callback(error); + } + + hooks.execPost(key, model, [res], function(error) { + if (error != null) { + return callback(error); + } + callback(null, res); + }); + } + }); + }, model.events); + }; + } + } +};
\ No newline at end of file diff --git a/node_modules/mongoose/lib/helpers/model/applyStatics.js b/node_modules/mongoose/lib/helpers/model/applyStatics.js new file mode 100644 index 0000000..3b9501e --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/applyStatics.js @@ -0,0 +1,12 @@ +'use strict'; + +/*! + * Register statics for this model + * @param {Model} model + * @param {Schema} schema + */ +module.exports = function applyStatics(model, schema) { + for (const i in schema.statics) { + model[i] = schema.statics[i]; + } +}; diff --git a/node_modules/mongoose/lib/helpers/model/castBulkWrite.js b/node_modules/mongoose/lib/helpers/model/castBulkWrite.js new file mode 100644 index 0000000..6e7a830 --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/castBulkWrite.js @@ -0,0 +1,224 @@ +'use strict'; + +const getDiscriminatorByValue = require('../../helpers/discriminator/getDiscriminatorByValue'); +const applyTimestampsToChildren = require('../update/applyTimestampsToChildren'); +const applyTimestampsToUpdate = require('../update/applyTimestampsToUpdate'); +const cast = require('../../cast'); +const castUpdate = require('../query/castUpdate'); +const setDefaultsOnInsert = require('../setDefaultsOnInsert'); + +/*! + * Given a model and a bulkWrite op, return a thunk that handles casting and + * validating the individual op. + */ + +module.exports = function castBulkWrite(originalModel, op, options) { + const now = originalModel.base.now(); + + if (op['insertOne']) { + return (callback) => { + const model = decideModelByObject(originalModel, op['insertOne']['document']); + + const doc = new model(op['insertOne']['document']); + if (model.schema.options.timestamps != null) { + doc.initializeTimestamps(); + } + if (options.session != null) { + doc.$session(options.session); + } + op['insertOne']['document'] = doc; + op['insertOne']['document'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error, null); + } + callback(null); + }); + }; + } else if (op['updateOne']) { + return (callback) => { + try { + if (!op['updateOne']['filter']) { + throw new Error('Must provide a filter object.'); + } + if (!op['updateOne']['update']) { + throw new Error('Must provide an update object.'); + } + + const model = decideModelByObject(originalModel, op['updateOne']['filter']); + const schema = model.schema; + const strict = options.strict != null ? options.strict : model.schema.options.strict; + + _addDiscriminatorToObject(schema, op['updateOne']['filter']); + + if (model.schema.$timestamps != null && op['updateOne'].timestamps !== false) { + const createdAt = model.schema.$timestamps.createdAt; + const updatedAt = model.schema.$timestamps.updatedAt; + applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateOne']['update'], {}); + } + + applyTimestampsToChildren(now, op['updateOne']['update'], model.schema); + + if (op['updateOne'].setDefaultsOnInsert) { + setDefaultsOnInsert(op['updateOne']['filter'], model.schema, op['updateOne']['update'], { + setDefaultsOnInsert: true, + upsert: op['updateOne'].upsert + }); + } + + op['updateOne']['filter'] = cast(model.schema, op['updateOne']['filter'], { + strict: strict, + upsert: op['updateOne'].upsert + }); + + op['updateOne']['update'] = castUpdate(model.schema, op['updateOne']['update'], { + strict: strict, + overwrite: false, + upsert: op['updateOne'].upsert + }, model, op['updateOne']['filter']); + } catch (error) { + return callback(error, null); + } + + callback(null); + }; + } else if (op['updateMany']) { + return (callback) => { + try { + if (!op['updateMany']['filter']) { + throw new Error('Must provide a filter object.'); + } + if (!op['updateMany']['update']) { + throw new Error('Must provide an update object.'); + } + + const model = decideModelByObject(originalModel, op['updateMany']['filter']); + const schema = model.schema; + const strict = options.strict != null ? options.strict : model.schema.options.strict; + + if (op['updateMany'].setDefaultsOnInsert) { + setDefaultsOnInsert(op['updateMany']['filter'], model.schema, op['updateMany']['update'], { + setDefaultsOnInsert: true, + upsert: op['updateMany'].upsert + }); + } + + if (model.schema.$timestamps != null && op['updateMany'].timestamps !== false) { + const createdAt = model.schema.$timestamps.createdAt; + const updatedAt = model.schema.$timestamps.updatedAt; + applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateMany']['update'], {}); + } + + applyTimestampsToChildren(now, op['updateMany']['update'], model.schema); + + _addDiscriminatorToObject(schema, op['updateMany']['filter']); + + op['updateMany']['filter'] = cast(model.schema, op['updateMany']['filter'], { + strict: strict, + upsert: op['updateMany'].upsert + }); + + op['updateMany']['update'] = castUpdate(model.schema, op['updateMany']['update'], { + strict: strict, + overwrite: false, + upsert: op['updateMany'].upsert + }, model, op['updateMany']['filter']); + + } catch (error) { + return callback(error, null); + } + + callback(null); + }; + } else if (op['replaceOne']) { + return (callback) => { + const model = decideModelByObject(originalModel, op['replaceOne']['filter']); + const schema = model.schema; + const strict = options.strict != null ? options.strict : model.schema.options.strict; + + _addDiscriminatorToObject(schema, op['replaceOne']['filter']); + try { + op['replaceOne']['filter'] = cast(model.schema, op['replaceOne']['filter'], { + strict: strict, + upsert: op['replaceOne'].upsert + }); + } catch (error) { + return callback(error, null); + } + + // set `skipId`, otherwise we get "_id field cannot be changed" + const doc = new model(op['replaceOne']['replacement'], strict, true); + if (model.schema.options.timestamps != null) { + doc.initializeTimestamps(); + } + if (options.session != null) { + doc.$session(options.session); + } + op['replaceOne']['replacement'] = doc; + + op['replaceOne']['replacement'].validate({ __noPromise: true }, function(error) { + if (error) { + return callback(error, null); + } + op['replaceOne']['replacement'] = op['replaceOne']['replacement'].toBSON(); + callback(null); + }); + }; + } else if (op['deleteOne']) { + return (callback) => { + const model = decideModelByObject(originalModel, op['deleteOne']['filter']); + const schema = model.schema; + + _addDiscriminatorToObject(schema, op['deleteOne']['filter']); + + try { + op['deleteOne']['filter'] = cast(model.schema, + op['deleteOne']['filter']); + } catch (error) { + return callback(error, null); + } + + callback(null); + }; + } else if (op['deleteMany']) { + return (callback) => { + const model = decideModelByObject(originalModel, op['deleteMany']['filter']); + const schema = model.schema; + + _addDiscriminatorToObject(schema, op['deleteMany']['filter']); + + try { + op['deleteMany']['filter'] = cast(model.schema, + op['deleteMany']['filter']); + } catch (error) { + return callback(error, null); + } + + callback(null); + }; + } else { + return (callback) => { + callback(new Error('Invalid op passed to `bulkWrite()`'), null); + }; + } +}; + +function _addDiscriminatorToObject(schema, obj) { + if (schema == null) { + return; + } + if (schema.discriminatorMapping && !schema.discriminatorMapping.isRoot) { + obj[schema.discriminatorMapping.key] = schema.discriminatorMapping.value; + } +} + +/*! + * gets discriminator model if discriminator key is present in object + */ + +function decideModelByObject(model, object) { + const discriminatorKey = model.schema.options.discriminatorKey; + if (object != null && object.hasOwnProperty(discriminatorKey)) { + model = getDiscriminatorByValue(model, object[discriminatorKey]) || model; + } + return model; +}
\ No newline at end of file diff --git a/node_modules/mongoose/lib/helpers/model/discriminator.js b/node_modules/mongoose/lib/helpers/model/discriminator.js new file mode 100644 index 0000000..2ad4c5e --- /dev/null +++ b/node_modules/mongoose/lib/helpers/model/discriminator.js @@ -0,0 +1,205 @@ +'use strict'; + +const Mixed = require('../../schema/mixed'); +const defineKey = require('../document/compile').defineKey; +const get = require('../get'); +const utils = require('../../utils'); + +const CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = { + toJSON: true, + toObject: true, + _id: true, + id: true +}; + +/*! + * ignore + */ + +module.exports = function discriminator(model, name, schema, tiedValue, applyPlugins) { + if (!(schema && schema.instanceOfSchema)) { + throw new Error('You must pass a valid discriminator Schema'); + } + + if (model.schema.discriminatorMapping && + !model.schema.discriminatorMapping.isRoot) { + throw new Error('Discriminator "' + name + + '" can only be a discriminator of the root model'); + } + + if (applyPlugins) { + const applyPluginsToDiscriminators = get(model.base, + 'options.applyPluginsToDiscriminators', false); + // Even if `applyPluginsToDiscriminators` isn't set, we should still apply + // global plugins to schemas embedded in the discriminator schema (gh-7370) + model.base._applyPlugins(schema, { + skipTopLevel: !applyPluginsToDiscriminators + }); + } + + const key = model.schema.options.discriminatorKey; + + const existingPath = model.schema.path(key); + if (existingPath != null) { + if (!utils.hasUserDefinedProperty(existingPath.options, 'select')) { + existingPath.options.select = true; + } + existingPath.options.$skipDiscriminatorCheck = true; + } else { + const baseSchemaAddition = {}; + baseSchemaAddition[key] = { + default: void 0, + select: true, + $skipDiscriminatorCheck: true + }; + baseSchemaAddition[key][model.schema.options.typeKey] = String; + model.schema.add(baseSchemaAddition); + defineKey(key, null, model.prototype, null, [key], model.schema.options); + } + + if (schema.path(key) && schema.path(key).options.$skipDiscriminatorCheck !== true) { + throw new Error('Discriminator "' + name + + '" cannot have field with name "' + key + '"'); + } + + let value = name; + if (typeof tiedValue == 'string' && tiedValue.length) { + value = tiedValue; + } + + function merge(schema, baseSchema) { + // Retain original schema before merging base schema + schema._baseSchema = baseSchema; + if (baseSchema.paths._id && + baseSchema.paths._id.options && + !baseSchema.paths._id.options.auto) { + schema.remove('_id'); + } + + // Find conflicting paths: if something is a path in the base schema + // and a nested path in the child schema, overwrite the base schema path. + // See gh-6076 + const baseSchemaPaths = Object.keys(baseSchema.paths); + const conflictingPaths = []; + + for (const path of baseSchemaPaths) { + if (schema.nested[path]) { + conflictingPaths.push(path); + continue; + } + + if (path.indexOf('.') === -1) { + continue; + } + const sp = path.split('.').slice(0, -1); + let cur = ''; + for (const piece of sp) { + cur += (cur.length ? '.' : '') + piece; + if (schema.paths[cur] instanceof Mixed || + schema.singleNestedPaths[cur] instanceof Mixed) { + conflictingPaths.push(path); + } + } + } + + utils.merge(schema, baseSchema, { + isDiscriminatorSchemaMerge: true, + omit: { discriminators: true, base: true }, + omitNested: conflictingPaths.reduce((cur, path) => { + cur['tree.' + path] = true; + return cur; + }, {}) + }); + + // Clean up conflicting paths _after_ merging re: gh-6076 + for (const conflictingPath of conflictingPaths) { + delete schema.paths[conflictingPath]; + } + + // Rebuild schema models because schemas may have been merged re: #7884 + schema.childSchemas.forEach(obj => { + obj.model.prototype.$__setSchema(obj.schema); + }); + + const obj = {}; + obj[key] = { + default: value, + select: true, + set: function(newName) { + if (newName === value) { + return value; + } + throw new Error('Can\'t set discriminator key "' + key + '"'); + }, + $skipDiscriminatorCheck: true + }; + obj[key][schema.options.typeKey] = existingPath ? + existingPath.instance : + String; + schema.add(obj); + schema.discriminatorMapping = { key: key, value: value, isRoot: false }; + + if (baseSchema.options.collection) { + schema.options.collection = baseSchema.options.collection; + } + + const toJSON = schema.options.toJSON; + const toObject = schema.options.toObject; + const _id = schema.options._id; + const id = schema.options.id; + + const keys = Object.keys(schema.options); + schema.options.discriminatorKey = baseSchema.options.discriminatorKey; + + for (const _key of keys) { + if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) { + // Special case: compiling a model sets `pluralization = true` by default. Avoid throwing an error + // for that case. See gh-9238 + if (_key === 'pluralization' && schema.options[_key] == true && baseSchema.options[_key] == null) { + continue; + } + + if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) { + throw new Error('Can\'t customize discriminator option ' + _key + + ' (can only modify ' + + Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') + + ')'); + } + } + } + schema.options = utils.clone(baseSchema.options); + if (toJSON) schema.options.toJSON = toJSON; + if (toObject) schema.options.toObject = toObject; + if (typeof _id !== 'undefined') { + schema.options._id = _id; + } + schema.options.id = id; + schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks); + + schema.plugins = Array.prototype.slice.call(baseSchema.plugins); + schema.callQueue = baseSchema.callQueue.concat(schema.callQueue); + delete schema._requiredpaths; // reset just in case Schema#requiredPaths() was called on either schema + } + + // merges base schema into new discriminator schema and sets new type field. + merge(schema, model.schema); + + if (!model.discriminators) { + model.discriminators = {}; + } + + if (!model.schema.discriminatorMapping) { + model.schema.discriminatorMapping = { key: key, value: null, isRoot: true }; + } + if (!model.schema.discriminators) { + model.schema.discriminators = {}; + } + + model.schema.discriminators[name] = schema; + + if (model.discriminators[name]) { + throw new Error('Discriminator with name "' + name + '" already exists'); + } + + return schema; +}; |