Files
DiceCloud/app/imports/api/parenting/parenting.js

166 lines
4.0 KiB
JavaScript

import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
// n = collections.length
let collections = [];
export function registerCollection(collectionName){
collections.push(collectionName);
};
// 1 database hit to get the parent by reference
export function fetchParent({id, collection}){
return fetchDocByRef({id, collection});
};
// n database hits to get the children by parent id
export function fetchChildren({parentId, filter = {}, options}){
filter["parent.id"] = parentId;
let children = [];
collections.forEach(collection => {
children.push(
...collection.find({
"parent.id": parentId
}, options).fetch()
);
});
return children;
}
// n database hits to update the decendents
export function updateChildren({parentId, filter = {}, modifier, options={}}){
filter["parent.id"] = parentId;
options.multi = true;
collections.forEach(collection => {
collection.update(filter, modifier, options);
});
};
// n database hits to fetch the decendents by ancestor id, in no particular order
export function fetchDecendents({ancestorId, filter = {}, options}){
filter["ancestors.id"] = ancestorId;
let decendents = [];
collections.forEach(collection => {
decendents.push(...collection.find(filter, options).fetch());
});
return decendents;
};
// n database hits to update the decendents
export function updateDecendents({ancestorId, filter = {}, modifier, options={}}){
filter["ancestors.id"] = ancestorId;
options.multi = true;
collections.forEach(collection => {
collection.update(filter, modifier, options);
});
};
// n database hits to get decendents to act on
export function forEachDecendent({ancestorId, filter = {}, options}, callback){
filter["ancestors.id"] = ancestorId;
collections.forEach(collection => {
collection.find(filter, options).forEach(callback);
});
};
// 1 database read
export function getParenting({id, collection}){
// Get the parent ref
let parentDoc = fetchDocByRef({id, collection}, {fields: {
name: 1,
enabled: 1,
ancestors: 1,
}});
let parent = {
id,
collection,
name: parentDoc.name,
enabled: parentDoc.enabled,
};
// Ancestors is [...parent's ancestors, parent ref]
let ancestors = parentDoc.ancestors;
ancestors.push(parent);
return {parent, ancestors};
}
export function updateParent(docRef, parentRef){
let collection = getCollectionByName(docRef.collection);
let oldDoc = fetchDocByRef(docRef, {fields: {
parent: 1,
ancestors: 1,
}});
// Skip if we aren't changing the parent id
if (oldDoc.parent.id === parentRef.id) return;
// update the document's parenting
let {parent, ancestors} = getParenting(parentRef);
collection.update(docRef.id, {$set: {parent, ancestors}});
// Remove the old ancestors from the decendents
updateDecendents({
ancestorId: docRef.id,
modifier: {$pullAll: {
ancestors: oldDoc.ancestors,
}},
});
// Add the new ancestors to the decendents
updateDecendents({
ancestorId: docRef.id,
modifier: {$push: {
ancestors: {
$each: ancestors,
$position: 0,
},
}},
});
};
export function setInheritedField({id, collection, fieldName, fieldValue}){
// Update the doc
let collection = getCollectionByName(collection);
collection.update(id, {$set: {
[`${fieldName}`]: fieldValue,
}});
// Update the parent object of its children
updateChildren({
parentId: id,
modifier: {$set: {
[`parent.${fieldName}`]: fieldValue,
}},
});
// Update the ancestors object of its decendents
updateDecendents({
ancestorId: id,
modifier: {$set: {
[`ancestors.$.${fieldName}`]: fieldValue,
}},
});
};
export function setEnabled({id, collection, enabled}){
setInheritedField({
id,
collection,
fieldName: 'enabled',
fieldValue: enabled,
});
};
export function setName({id, collection, name}){
setInheritedField({
id,
collection,
fieldName: 'name',
fieldValue: name,
});
};