user model added; message model changed; tag model added

This commit is contained in:
mandutzse68104 committed 2019-06-04 14:50:37 +02:00
1 parent d27216c8a8
commit f6a8c83586
5156 files changed
+62 -437424

No files matched your search

-71
View File
@@ -1,71 +0,0 @@
'use strict';
/*!
* Module dependencies.
*/
const async = require('async');
const utils = require('../../utils');
/**
* Execute `fn` for every document in the cursor. If `fn` returns a promise,
* will wait for the promise to resolve before iterating on to the next one.
* Returns a promise that resolves when done.
*
* @param {Function} next the thunk to call to get the next document
* @param {Function} fn
* @param {Object} options
* @param {Function} [callback] executed when all docs have been processed
* @return {Promise}
* @api public
* @method eachAsync
*/
module.exports = function eachAsync(next, fn, options, callback) {
const parallel = options.parallel || 1;
const handleNextResult = function(doc, callback) {
const promise = fn(doc);
if (promise && typeof promise.then === 'function') {
promise.then(
function() { callback(null); },
function(error) { callback(error || new Error('`eachAsync()` promise rejected without error')); });
} else {
callback(null);
}
};
const iterate = function(callback) {
let drained = false;
const nextQueue = async.queue(function(task, cb) {
if (drained) return cb();
next(function(err, doc) {
if (err) return cb(err);
if (!doc) drained = true;
cb(null, doc);
});
}, 1);
const getAndRun = function(cb) {
nextQueue.push({}, function(err, doc) {
if (err) return cb(err);
if (!doc) return cb();
handleNextResult(doc, function(err) {
if (err) return cb(err);
// Make sure to clear the stack re: gh-4697
setTimeout(function() {
getAndRun(cb);
}, 0);
});
});
};
async.times(parallel, function(n, cb) {
getAndRun(cb);
}, callback);
};
return utils.promiseOrCallback(callback, cb => {
iterate(cb);
});
};
-12
View File
@@ -1,12 +0,0 @@
/*!
* Centralize this so we can more easily work around issues with people
* stubbing out `process.nextTick()` in tests using sinon:
* https://github.com/sinonjs/lolex#automatically-incrementing-mocked-time
* See gh-6074
*/
'use strict';
module.exports = function immediate(cb) {
return process.nextTick(cb);
};
-12
View File
@@ -1,12 +0,0 @@
'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];
}
};
-61
View File
@@ -1,61 +0,0 @@
'use strict';
module.exports = getVirtual;
/*!
* ignore
*/
function getVirtual(schema, name) {
if (schema.virtuals[name]) {
return schema.virtuals[name];
}
const parts = name.split('.');
let cur = '';
let nestedSchemaPath = '';
for (let i = 0; i < parts.length; ++i) {
cur += (cur.length > 0 ? '.' : '') + parts[i];
if (schema.virtuals[cur]) {
if (i === parts.length - 1) {
schema.virtuals[cur].$nestedSchemaPath = nestedSchemaPath;
return schema.virtuals[cur];
}
continue;
}
if (schema.nested[cur]) {
continue;
}
if (schema.paths[cur] && schema.paths[cur].schema) {
schema = schema.paths[cur].schema;
const rest = parts.slice(i + 1).join('.');
if (schema.virtuals[rest]) {
if (i === parts.length - 2) {
schema.virtuals[rest].$nestedSchemaPath =
[nestedSchemaPath, cur].filter(v => !!v).join('.');
return schema.virtuals[rest];
}
continue;
}
if (i + 1 < parts.length && schema.discriminators) {
for (const key of Object.keys(schema.discriminators)) {
const _virtual = getVirtual(schema.discriminators[key], rest);
if (_virtual != null) {
_virtual.$nestedSchemaPath = [nestedSchemaPath, cur].
filter(v => !!v).join('.');
return _virtual;
}
}
}
nestedSchemaPath += (nestedSchemaPath.length > 0 ? '.' : '') + cur;
cur = '';
continue;
}
return null;
}
}
-18
View File
@@ -1,18 +0,0 @@
'use strict';
/*!
* ignore
*/
module.exports = function isDefiningProjection(val) {
if (val == null) {
// `undefined` or `null` become exclusive projections
return true;
}
if (typeof val === 'object') {
// Only cases where a value does **not** define whether the whole projection
// is inclusive or exclusive are `$meta` and `$slice`.
return !('$meta' in val) && !('$slice' in val);
}
return true;
};
-28
View File
@@ -1,28 +0,0 @@
'use strict';
const isDefiningProjection = require('./isDefiningProjection');
/*!
* ignore
*/
module.exports = function isExclusive(projection) {
const keys = Object.keys(projection);
let ki = keys.length;
let exclude = null;
if (ki === 1 && keys[0] === '_id') {
exclude = !!projection[keys[ki]];
} else {
while (ki--) {
// Does this projection explicitly define inclusion/exclusion?
// Explicitly avoid `$meta` and `$slice`
if (keys[ki] !== '_id' && isDefiningProjection(projection[keys[ki]])) {
exclude = !projection[keys[ki]];
break;
}
}
}
return exclude;
};
-34
View File
@@ -1,34 +0,0 @@
'use strict';
const isDefiningProjection = require('./isDefiningProjection');
/*!
* ignore
*/
module.exports = function isInclusive(projection) {
if (projection == null) {
return false;
}
const props = Object.keys(projection);
const numProps = props.length;
if (numProps === 0) {
return false;
}
for (let i = 0; i < numProps; ++i) {
const prop = props[i];
// Plus paths can't define the projection (see gh-7050)
if (prop.charAt(0) === '+') {
continue;
}
// If field is truthy (1, true, etc.) and not an object, then this
// projection must be inclusive. If object, assume its $meta, $slice, etc.
if (isDefiningProjection(projection[prop]) && !!projection[prop]) {
return true;
}
}
return false;
};
-35
View File
@@ -1,35 +0,0 @@
'use strict';
const isDefiningProjection = require('./isDefiningProjection');
/*!
* Determines if `path` is excluded by `projection`
*
* @param {Object} projection
* @param {string} path
* @return {Boolean}
*/
module.exports = function isPathExcluded(projection, path) {
if (path === '_id') {
return projection._id === 0;
}
const paths = Object.keys(projection);
let type = null;
for (const _path of paths) {
if (isDefiningProjection(projection[_path])) {
type = projection[path] === 1 ? 'inclusive' : 'exclusive';
break;
}
}
if (type === 'inclusive') {
return projection[path] !== 1;
}
if (type === 'exclusive') {
return projection[path] === 0;
}
return false;
};
@@ -1,28 +0,0 @@
'use strict';
/*!
* ignore
*/
module.exports = function isPathSelectedInclusive(fields, path) {
const chunks = path.split('.');
let cur = '';
let j;
let keys;
let numKeys;
for (let i = 0; i < chunks.length; ++i) {
cur += cur.length ? '.' : '' + chunks[i];
if (fields[cur]) {
keys = Object.keys(fields);
numKeys = keys.length;
for (j = 0; j < numKeys; ++j) {
if (keys[i].indexOf(cur + '.') === 0 && keys[i].indexOf(path) !== 0) {
continue;
}
}
return true;
}
}
return false;
};
-47
View File
@@ -1,47 +0,0 @@
'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
*/
function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
const arr = [];
let count = docs.length;
const len = count;
let error = null;
function init(_error) {
if (_error != null) {
error = error || _error;
}
if (error != null) {
--count || process.nextTick(() => callback(error));
return;
}
--count || process.nextTick(() => callback(error, arr));
}
for (let i = 0; i < len; ++i) {
arr[i] = helpers.createModel(model, docs[i], fields, userProvidedFields);
try {
arr[i].init(docs[i], opts, init);
} catch (error) {
init(error);
}
arr[i].$session(opts.session);
}
}
-16
View File
@@ -1,16 +0,0 @@
'use strict';
/*!
* ignore
*/
module.exports = function(obj) {
const keys = Object.keys(obj);
const len = keys.length;
for (let i = 0; i < len; ++i) {
if (keys[i].charAt(0) === '$') {
return true;
}
}
return false;
};
-46
View File
@@ -1,46 +0,0 @@
'use strict';
/*!
* ignore
*/
module.exports = function selectPopulatedFields(query) {
const opts = query._mongooseOptions;
if (opts.populate != null) {
const paths = Object.keys(opts.populate);
const userProvidedFields = query._userProvidedFields || {};
if (query.selectedInclusively()) {
for (let i = 0; i < paths.length; ++i) {
if (!isPathInFields(userProvidedFields, paths[i])) {
query.select(paths[i]);
} else if (userProvidedFields[paths[i]] === 0) {
delete query._fields[paths[i]];
}
}
} else if (query.selectedExclusively()) {
for (let i = 0; i < paths.length; ++i) {
if (userProvidedFields[paths[i]] == null) {
delete query._fields[paths[i]];
}
}
}
}
};
/*!
* 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) {
return true;
}
cur += '.' + pieces[i];
}
return userProvidedFields[cur] != null;
}
-16
View File
@@ -1,16 +0,0 @@
'use strict';
const get = require('../get');
module.exports = function applyWriteConcern(schema, options) {
const writeConcern = get(schema, 'options.writeConcern', {});
if (!('w' in options) && writeConcern.w != null) {
options.w = writeConcern.w;
}
if (!('j' in options) && writeConcern.j != null) {
options.j = writeConcern.j;
}
if (!('wtimeout' in options) && writeConcern.wtimeout != null) {
options.wtimeout = writeConcern.wtimeout;
}
};
-124
View File
@@ -1,124 +0,0 @@
'use strict';
const get = require('../get');
const utils = require('../../utils');
/*!
* Gather all indexes defined in the schema, including single nested,
* document arrays, and embedded discriminators.
*/
module.exports = function getIndexes(schema) {
let indexes = [];
const schemaStack = new WeakMap();
const indexTypes = schema.constructor.indexTypes;
const collectIndexes = function(schema, prefix) {
// Ignore infinitely nested schemas, if we've already seen this schema
// along this path there must be a cycle
if (schemaStack.has(schema)) {
return;
}
schemaStack.set(schema, true);
prefix = prefix || '';
const keys = Object.keys(schema.paths);
const length = keys.length;
for (let i = 0; i < length; ++i) {
const key = keys[i];
const path = schema.paths[key];
if (path.$isMongooseDocumentArray || path.$isSingleNested) {
if (get(path, 'options.excludeIndexes') !== true &&
get(path, 'schemaOptions.excludeIndexes') !== true) {
collectIndexes(path.schema, prefix + key + '.');
}
if (path.schema.discriminators != null) {
const discriminators = path.schema.discriminators;
const discriminatorKeys = Object.keys(discriminators);
for (const discriminatorKey of discriminatorKeys) {
collectIndexes(discriminators[discriminatorKey]._originalSchema,
prefix + key + '.');
}
}
// Retained to minimize risk of backwards breaking changes due to
// gh-6113
if (path.$isMongooseDocumentArray) {
continue;
}
}
const index = path._index || (path.caster && path.caster._index);
if (index !== false && index !== null && index !== undefined) {
const field = {};
const isObject = utils.isObject(index);
const options = isObject ? index : {};
const type = typeof index === 'string' ? index :
isObject ? index.type :
false;
if (type && indexTypes.indexOf(type) !== -1) {
field[prefix + key] = type;
} else if (options.text) {
field[prefix + key] = 'text';
delete options.text;
} else {
field[prefix + key] = 1;
}
delete options.type;
if (!('background' in options)) {
options.background = true;
}
indexes.push([field, options]);
}
}
schemaStack.delete(schema);
if (prefix) {
fixSubIndexPaths(schema, prefix);
} else {
schema._indexes.forEach(function(index) {
if (!('background' in index[1])) {
index[1].background = true;
}
});
indexes = indexes.concat(schema._indexes);
}
};
collectIndexes(schema);
return indexes;
/*!
* Checks for indexes added to subdocs using Schema.index().
* These indexes need their paths prefixed properly.
*
* schema._indexes = [ [indexObj, options], [indexObj, options] ..]
*/
function fixSubIndexPaths(schema, prefix) {
const subindexes = schema._indexes;
const len = subindexes.length;
for (let i = 0; i < len; ++i) {
const indexObj = subindexes[i][0];
const keys = Object.keys(indexObj);
const klen = keys.length;
const newindex = {};
// use forward iteration, order matters
for (let j = 0; j < klen; ++j) {
const key = keys[j];
newindex[prefix + key] = indexObj[key];
}
indexes.push([newindex, subindexes[i][1]]);
}
}
};
-117
View File
@@ -1,117 +0,0 @@
'use strict';
const modifiedPaths = require('./common').modifiedPaths;
/**
* Applies defaults to update and findOneAndUpdate operations.
*
* @param {Object} filter
* @param {Schema} schema
* @param {Object} castedDoc
* @param {Object} options
* @method setDefaultsOnInsert
* @api private
*/
module.exports = function(filter, schema, castedDoc, options) {
const keys = Object.keys(castedDoc || {});
const updatedKeys = {};
const updatedValues = {};
const numKeys = keys.length;
const modified = {};
let hasDollarUpdate = false;
options = options || {};
if (!options.upsert || !options.setDefaultsOnInsert) {
return castedDoc;
}
for (let i = 0; i < numKeys; ++i) {
if (keys[i].charAt(0) === '$') {
modifiedPaths(castedDoc[keys[i]], '', modified);
hasDollarUpdate = true;
}
}
if (!hasDollarUpdate) {
modifiedPaths(castedDoc, '', modified);
}
const paths = Object.keys(filter);
const numPaths = paths.length;
for (let i = 0; i < numPaths; ++i) {
const path = paths[i];
const condition = filter[path];
if (condition && typeof condition === 'object') {
const conditionKeys = Object.keys(condition);
const numConditionKeys = conditionKeys.length;
let hasDollarKey = false;
for (let j = 0; j < numConditionKeys; ++j) {
if (conditionKeys[j].charAt(0) === '$') {
hasDollarKey = true;
break;
}
}
if (hasDollarKey) {
continue;
}
}
updatedKeys[path] = true;
modified[path] = true;
}
if (options && options.overwrite && !hasDollarUpdate) {
// Defaults will be set later, since we're overwriting we'll cast
// the whole update to a document
return castedDoc;
}
schema.eachPath(function(path, schemaType) {
if (schemaType.$isSingleNested) {
// Only handle nested schemas 1-level deep to avoid infinite
// recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
schemaType.schema.eachPath(function(_path, _schemaType) {
if (_path === '_id' && _schemaType.auto) {
// Ignore _id if auto id so we don't create subdocs
return;
}
const def = _schemaType.getDefault(null, true);
if (!isModified(modified, path + '.' + _path) &&
typeof def !== 'undefined') {
castedDoc = castedDoc || {};
castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
castedDoc.$setOnInsert[path + '.' + _path] = def;
updatedValues[path + '.' + _path] = def;
}
});
} else {
const def = schemaType.getDefault(null, true);
if (!isModified(modified, path) && typeof def !== 'undefined') {
castedDoc = castedDoc || {};
castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
castedDoc.$setOnInsert[path] = def;
updatedValues[path] = def;
}
}
});
return castedDoc;
};
function isModified(modified, path) {
if (modified[path]) {
return true;
}
const sp = path.split('.');
let cur = sp[0];
for (let i = 1; i < sp.length; ++i) {
if (modified[cur]) {
return true;
}
cur += '.' + sp[i];
}
return false;
}
-65
View File
@@ -1,65 +0,0 @@
'use strict';
/*!
* ignore
*/
const get = require('../get');
module.exports = applyTimestampsToUpdate;
/*!
* ignore
*/
function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, options) {
const updates = currentUpdate;
let _updates = updates;
const overwrite = get(options, 'overwrite', false);
const timestamps = get(options, 'timestamps', true);
// Support skipping timestamps at the query level, see gh-6980
if (!timestamps || updates == null) {
return currentUpdate;
}
if (overwrite) {
if (currentUpdate && currentUpdate.$set) {
currentUpdate = currentUpdate.$set;
updates.$set = {};
_updates = updates.$set;
}
if (updatedAt && !currentUpdate[updatedAt]) {
_updates[updatedAt] = now;
}
if (createdAt && !currentUpdate[createdAt]) {
_updates[createdAt] = now;
}
return updates;
}
updates.$set = updates.$set || {};
currentUpdate = currentUpdate || {};
if (updatedAt &&
(!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt])) {
updates.$set[updatedAt] = now;
}
if (createdAt) {
if (currentUpdate[createdAt]) {
delete currentUpdate[createdAt];
}
if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
delete currentUpdate.$set[createdAt];
}
updates.$setOnInsert = updates.$setOnInsert || {};
updates.$setOnInsert[createdAt] = now;
}
if (Object.keys(updates.$set).length === 0) {
delete updates.$set;
}
return updates;
}
-33
View File
@@ -1,33 +0,0 @@
'use strict';
const _modifiedPaths = require('../common').modifiedPaths;
/**
* Given an update document with potential update operators (`$set`, etc.)
* returns an object whose keys are the directly modified paths.
*
* If there are any top-level keys that don't start with `$`, we assume those
* will get wrapped in a `$set`. The Mongoose Query is responsible for wrapping
* top-level keys in `$set`.
*
* @param {Object} update
* @return {Object} modified
*/
module.exports = function modifiedPaths(update) {
const keys = Object.keys(update);
const res = {};
const withoutDollarKeys = {};
for (const key of keys) {
if (key.startsWith('$')) {
_modifiedPaths(update[key], '', res);
continue;
}
withoutDollarKeys[key] = update[key];
}
_modifiedPaths(withoutDollarKeys, '', res);
return res;
};