copies autopopulate for our own usage
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
export function createAutopopulateOptions(depth) {
|
||||
const autopopulateOptions = {};
|
||||
export function createAutopopulateOptions({ depth, locale, fallback }) {
|
||||
const autopopulateOptions = {
|
||||
locale,
|
||||
fallback
|
||||
};
|
||||
|
||||
if (typeof depth != 'undefined') {
|
||||
autopopulateOptions.maxDepth = depth;
|
||||
if (depth === '0') {
|
||||
autopopulateOptions.autopopulate = false;
|
||||
}
|
||||
}
|
||||
return autopopulateOptions;
|
||||
return {
|
||||
autopopulate: autopopulateOptions
|
||||
};
|
||||
}
|
||||
|
||||
146
src/plugins/autopopulate.js
Normal file
146
src/plugins/autopopulate.js
Normal file
@@ -0,0 +1,146 @@
|
||||
'use strict';
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
module.exports = function (schema) {
|
||||
const pathsToPopulate = [];
|
||||
|
||||
eachPathRecursive(schema, (pathname, schemaType) => {
|
||||
let option;
|
||||
if (schemaType.options && schemaType.options.autopopulate) {
|
||||
option = schemaType.options.autopopulate;
|
||||
pathsToPopulate.push({
|
||||
options: defaultOptions(pathname, schemaType.options),
|
||||
autopopulate: option
|
||||
});
|
||||
} else if (schemaType.options &&
|
||||
schemaType.options.type &&
|
||||
schemaType.options.type[0] &&
|
||||
schemaType.options.type[0].autopopulate) {
|
||||
option = schemaType.options.type[0].autopopulate;
|
||||
pathsToPopulate.push({
|
||||
options: defaultOptions(pathname, schemaType.options.type[0]),
|
||||
autopopulate: option
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (schema.virtuals) {
|
||||
Object.keys(schema.virtuals).forEach((pathname) => {
|
||||
if (schema.virtuals[pathname].options.autopopulate) {
|
||||
pathsToPopulate.push({
|
||||
options: defaultOptions(pathname, schema.virtuals[pathname].options),
|
||||
autopopulate: schema.virtuals[pathname].options.autopopulate,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var autopopulateHandler = function () {
|
||||
if (this._mongooseOptions &&
|
||||
this._mongooseOptions.lean &&
|
||||
// If lean and user didn't explicitly do `lean({ autopulate: true })`,
|
||||
// skip it. See gh-27, gh-14, gh-48
|
||||
!this._mongooseOptions.lean.autopopulate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options = this.options || {};
|
||||
if (options.autopopulate === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const depth = options._depth != null ? options._depth : 0;
|
||||
if (options.maxDepth > 0 && depth >= options.maxDepth) {
|
||||
return;
|
||||
}
|
||||
|
||||
const numPaths = pathsToPopulate.length;
|
||||
for (let i = 0; i < numPaths; ++i) {
|
||||
pathsToPopulate[i].options = pathsToPopulate[i].options || {};
|
||||
pathsToPopulate[i].options.options = pathsToPopulate[i].options.options || {};
|
||||
Object.assign(pathsToPopulate[i].options.options, {
|
||||
...options,
|
||||
_depth: depth + 1
|
||||
});
|
||||
processOption.call(this,
|
||||
pathsToPopulate[i].autopopulate, pathsToPopulate[i].options);
|
||||
}
|
||||
};
|
||||
|
||||
schema.
|
||||
pre('find', autopopulateHandler).
|
||||
pre('findOne', autopopulateHandler).
|
||||
pre('findOneAndUpdate', autopopulateHandler);
|
||||
};
|
||||
|
||||
function defaultOptions(pathname, v) {
|
||||
const ret = { path: pathname, options: { maxDepth: 10 } };
|
||||
if (v.ref != null) {
|
||||
ret.model = v.ref;
|
||||
ret.ref = v.ref;
|
||||
}
|
||||
if (v.refPath != null) {
|
||||
ret.refPath = v.refPath;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function processOption(value, options) {
|
||||
switch (typeof value) {
|
||||
case 'function':
|
||||
handleFunction.call(this, value, options);
|
||||
break;
|
||||
case 'object':
|
||||
handleObject.call(this, value, options);
|
||||
break;
|
||||
default:
|
||||
handlePrimitive.call(this, value, options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handlePrimitive(value, options) {
|
||||
if (value) {
|
||||
this.populate(options);
|
||||
}
|
||||
}
|
||||
|
||||
function handleObject(value, optionsToUse) {
|
||||
// Special case: support top-level `maxDepth`
|
||||
if (value.maxDepth != null) {
|
||||
optionsToUse.options = optionsToUse.options || {};
|
||||
optionsToUse.options.maxDepth = value.maxDepth;
|
||||
delete value.maxDepth;
|
||||
}
|
||||
optionsToUse = Object.assign({}, optionsToUse, value);
|
||||
this.populate(optionsToUse);
|
||||
}
|
||||
|
||||
function handleFunction(fn, options) {
|
||||
const val = fn.call(this, options);
|
||||
processOption.call(this, val, options);
|
||||
}
|
||||
|
||||
function mergeOptions(destination, source) {
|
||||
const keys = Object.keys(source);
|
||||
const numKeys = keys.length;
|
||||
for (let i = 0; i < numKeys; ++i) {
|
||||
destination[keys[i]] = source[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
function eachPathRecursive(schema, handler, path) {
|
||||
if (!path) {
|
||||
path = [];
|
||||
}
|
||||
schema.eachPath((pathname, schemaType) => {
|
||||
path.push(pathname);
|
||||
if (schemaType.schema) {
|
||||
eachPathRecursive(schemaType.schema, handler, path);
|
||||
} else {
|
||||
handler(path.join('.'), schemaType);
|
||||
}
|
||||
path.pop();
|
||||
});
|
||||
}
|
||||
@@ -19,6 +19,7 @@ export default function internationalization(schema, options) {
|
||||
}
|
||||
|
||||
schema.eachPath((path, schemaType) => {
|
||||
|
||||
if (schemaType.schema) { // propagate plugin initialization for sub-documents schemas
|
||||
schemaType.schema.plugin(internationalization, pluginOptions);
|
||||
return;
|
||||
@@ -51,6 +52,7 @@ export default function internationalization(schema, options) {
|
||||
|
||||
schema.virtual(path)
|
||||
.get(function () {
|
||||
|
||||
// embedded and sub-documents will use locale methods from the top level document
|
||||
let owner = this.ownerDocument ? this.ownerDocument() : this,
|
||||
locale = owner.getLocale(),
|
||||
|
||||
@@ -8,9 +8,11 @@ const findOne = (req, res) => {
|
||||
Model: req.model,
|
||||
id: req.params._id,
|
||||
locale: req.locale,
|
||||
fallback: req.query['fallback-locale']
|
||||
fallback: req.query['fallback-locale'],
|
||||
depth: req.query.depth
|
||||
};
|
||||
modelById(query, { ...createAutopopulateOptions(req.query.depth) })
|
||||
|
||||
modelById(query, createAutopopulateOptions(query))
|
||||
.then(doc => res.json(doc))
|
||||
.catch(err => res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: err }));
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import httpStatus from 'http-status';
|
||||
|
||||
const query = (req, res) => {
|
||||
|
||||
req.model.paginate(req.model.apiQuery(req.query, req.locale), {...req.query}, (err, result) => {
|
||||
req.model.paginate(req.model.apiQuery(req.query, req.locale), { ...req.query }, (err, result) => {
|
||||
if (err) {
|
||||
return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: err });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user