Skip to content

Commit

Permalink
docs(applyVirtuals): add jsdoc comments and clean up some unnecessary…
Browse files Browse the repository at this point in the history
… code
  • Loading branch information
vkarpov15 committed Sep 25, 2024
1 parent c143d8e commit 660aad0
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 51 deletions.
89 changes: 47 additions & 42 deletions lib/helpers/document/applyVirtuals.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ const mpath = require('mpath');

module.exports = applyVirtuals;

function applyVirtuals(schema, doc, virtuals, parent) {
/**
* Apply a given schema's virtuals to a given POJO
*
* @param {Schema} schema
* @param {Object} doc
* @param {Array<string>} [virtuals] optional whitelist of virtuals to apply
* @returns
*/

function applyVirtuals(schema, doc, virtuals) {
if (doc == null) {
return doc;
}
Expand All @@ -15,9 +24,7 @@ function applyVirtuals(schema, doc, virtuals, parent) {
if (Array.isArray(virtuals)) {
virtualsForChildren = [];
toApply = [];
const len = virtuals.length;
for (let i = 0; i < len; ++i) {
const virtual = virtuals[i];
for (const virtual of virtuals) {
if (virtual.length === 1) {
toApply.push(virtual[0]);
} else {
Expand All @@ -26,28 +33,23 @@ function applyVirtuals(schema, doc, virtuals, parent) {
}
}

applyVirtualsToChildren(this, schema, doc, virtualsForChildren, parent);
return applyVirtualsToDocs(schema, doc, toApply);
applyVirtualsToChildren(schema, doc, virtualsForChildren);
return applyVirtualsToDoc(schema, doc, toApply);
}

function applyVirtualsToDocs(schema, res, toApply) {
if (Array.isArray(res)) {
const len = res.length;
for (let i = 0; i < len; ++i) {
applyVirtualsToDoc(schema, res[i], toApply);
}
return res;
} else {
return applyVirtualsToDoc(schema, res, toApply);
}
}
/**
* Apply virtuals to any subdocuments
*
* @param {Schema} schema subdocument schema
* @param {Object} res subdocument
* @param {Array<String>} [virtuals] optional whitelist of virtuals to apply
*/

function applyVirtualsToChildren(doc, schema, res, virtuals, parent) {
const len = schema.childSchemas.length;
function applyVirtualsToChildren(schema, res, virtuals) {
let attachedVirtuals = false;
for (let i = 0; i < len; ++i) {
const _path = schema.childSchemas[i].model.path;
const _schema = schema.childSchemas[i].schema;
for (const childSchema of schema.childSchemas) {
const _path = childSchema.model.path;
const _schema = childSchema.schema;
if (!_path) {
continue;
}
Expand All @@ -59,9 +61,7 @@ function applyVirtualsToChildren(doc, schema, res, virtuals, parent) {
let virtualsForChild = null;
if (Array.isArray(virtuals)) {
virtualsForChild = [];
const len = virtuals.length;
for (let i = 0; i < len; ++i) {
const virtual = virtuals[i];
for (const virtual of virtuals) {
if (virtual[0] == _path) {
virtualsForChild.push(virtual.slice(1));
}
Expand All @@ -72,22 +72,31 @@ function applyVirtualsToChildren(doc, schema, res, virtuals, parent) {
}
}

applyVirtuals.call(doc, _schema, _doc, virtualsForChild, res);
applyVirtuals(_schema, _doc, virtualsForChild);
attachedVirtuals = true;
}

if (virtuals && virtuals.length && !attachedVirtuals) {
applyVirtualsToDoc(schema, res, virtuals, parent);
applyVirtualsToDoc(schema, res, virtuals);
}
}

/**
* Apply virtuals to a given document. Does not apply virtuals to subdocuments: use `applyVirtualsToChildren` instead
*
* @param {Schema} schema
* @param {Object} doc
* @param {Array<String>} [virtuals] optional whitelist of virtuals to apply
* @returns
*/

function applyVirtualsToDoc(schema, doc, virtuals) {
if (doc == null || typeof doc !== 'object') {
return;
}
if (Array.isArray(doc)) {
for (let i = 0; i < doc.length; ++i) {
applyVirtualsToDoc(schema, doc[i], virtuals);
for (const el of doc) {
applyVirtualsToDoc(schema, el, virtuals);
}
return;
}
Expand All @@ -107,25 +116,25 @@ function applyVirtualsToDoc(schema, doc, virtuals) {
if (virtuals == null) {
virtuals = Object.keys(schema.virtuals);
}
const numVirtuals = virtuals.length;
for (let i = 0; i < numVirtuals; ++i) {
const virtual = virtuals[i];
for (const virtual of virtuals) {
if (schema.virtuals[virtual] == null) {
continue;
}
const virtualType = schema.virtuals[virtual];
const sp = Array.isArray(virtual)
? virtual :
virtual.indexOf('.') === -1
? virtual
: virtual.indexOf('.') === -1
? [virtual]
: virtual.split('.');
let cur = doc;
for (let j = 0; j < sp.length - 1; ++j) {
cur[sp[j]] = sp[j] in cur ? cur[sp[j]] : {};
cur = cur[sp[j]];
for (let i = 0; i < sp.length - 1; ++i) {
cur[sp[i]] = sp[i] in cur ? cur[sp[i]] : {};
cur = cur[sp[i]];
}
let val = virtualType.applyGetters(cur[sp[sp.length - 1]], doc);
if (isPopulateVirtual(virtualType) && val === undefined) {
const isPopulateVirtual =
virtualType.options && (virtualType.options.ref || virtualType.options.refPath);
if (isPopulateVirtual && val === undefined) {
if (virtualType.options.justOne) {
val = null;
} else {
Expand All @@ -135,7 +144,3 @@ function applyVirtualsToDoc(schema, doc, virtuals) {
cur[sp[sp.length - 1]] = val;
}
}

function isPopulateVirtual(virtualType) {
return virtualType.options && (virtualType.options.ref || virtualType.options.refPath);
}
18 changes: 9 additions & 9 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3521,24 +3521,24 @@ Model.applyDefaults = function applyDefaults(doc) {
* obj.name; // 'John'
* obj.upper; // 'JOHN', Mongoose applied the return value of the virtual to the given object
*
* @param {Object} doc object or document to apply virtuals on
* @param {Object} obj object or document to apply virtuals on
* @param {Array<string>} [virtualsToApply] optional whitelist of virtuals to apply
* @returns {Object} doc
* @returns {Object} obj
* @api public
*/

Model.applyVirtuals = function applyVirtuals(doc, virtualsToApply) {
if (doc == null) {
return doc;
Model.applyVirtuals = function applyVirtuals(obj, virtualsToApply) {
if (obj == null) {
return obj;
}
// Nothing to do if this is already a hydrated document - it should already have virtuals
if (doc.$__ != null) {
return doc;
if (obj.$__ != null) {
return obj;
}

applyVirtualsHelper(this.schema, doc, virtualsToApply, null);
applyVirtualsHelper(this.schema, obj, virtualsToApply);

return doc;
return obj;
};

/**
Expand Down

0 comments on commit 660aad0

Please sign in to comment.