formula-store
Advanced tools
Comparing version 1.0.0 to 1.1.0
154
lib/index.js
@@ -10,2 +10,70 @@ "use strict"; | ||
const fieldGraph = new fast_graph_1.Graph(); | ||
const checkFields = (fieldId, dependencies) => { | ||
const missingFields = dependencies.filter(d => !addedFields.has(d)); | ||
if (missingFields.length > 0) { | ||
throw new errors_1.FormulaFieldDependencyError(fieldId, missingFields); | ||
} | ||
}; | ||
const getPossibleTouchedFieldsOnNodeChange = (node, possiblyTouchedFields = new Set()) => { | ||
fieldGraph.bfs(n => { | ||
possiblyTouchedFields.add(n.id); | ||
return fast_graph_1.SearchAlgorithmNodeBehavior.continue; | ||
}, node); | ||
return possiblyTouchedFields; | ||
}; | ||
const computeRangeEditValueChanges = (possiblyTouchedFields, changes) => { | ||
for (const dep of dependencyTree) { | ||
if (!possiblyTouchedFields.has(dep.id)) { | ||
continue; | ||
} | ||
const node = addedFields.get(dep.id); | ||
if (node.calculate) { | ||
node.value = node.calculate(...node.incomingNeighbors.map(n => { | ||
const field = addedFields.get(n); | ||
return field.value; | ||
})); | ||
changes.push({ | ||
id: node.id, | ||
value: node.value | ||
}); | ||
} | ||
} | ||
}; | ||
const onFieldChanged = (node, dependencies) => { | ||
const values = []; | ||
for (const d of dependencies) { | ||
const parentField = addedFields.get(d); | ||
fieldGraph.addEdge(parentField, node); | ||
values.push(parentField.value); | ||
} | ||
try { | ||
dependencyTree = fieldGraph.kahnTopologicalSort(); | ||
} | ||
catch (ex) { | ||
fieldGraph.removeNode(node); | ||
throw new errors_1.FormulaFieldCircularDependencyError(node.id); | ||
} | ||
addedFields.set(node.id, node); | ||
if (dependencies.length && node.calculate) { | ||
node.value = node.calculate(...values); | ||
return [ | ||
{ | ||
id: node.id, | ||
value: node.value | ||
} | ||
]; | ||
} | ||
return []; | ||
}; | ||
const getFieldsToRecalculateOnNodeChanges = (field) => { | ||
const fieldToRecalculate = new Map(); | ||
fieldGraph.bfs(n => { | ||
const f = addedFields.get(n.id); | ||
if (f.calculate) { | ||
fieldToRecalculate.set(f.id, f); | ||
} | ||
return fast_graph_1.SearchAlgorithmNodeBehavior.continue; | ||
}, field); | ||
return fieldToRecalculate; | ||
}; | ||
return { | ||
@@ -17,10 +85,3 @@ removeField: fieldId => { | ||
const field = addedFields.get(fieldId); | ||
const fieldToRecalculate = new Map(); | ||
fieldGraph.bfs(n => { | ||
const f = addedFields.get(n.id); | ||
if (f.calculate) { | ||
fieldToRecalculate.set(f.id, f); | ||
} | ||
return fast_graph_1.SearchAlgorithmNodeBehavior.continue; | ||
}, field); | ||
const fieldToRecalculate = getFieldsToRecalculateOnNodeChanges(field); | ||
addedFields.delete(fieldId); | ||
@@ -47,2 +108,27 @@ fieldGraph.removeNode(field); | ||
}, | ||
editField: ({ id, value, dependencies, calculate }) => { | ||
checkFields(id, dependencies); | ||
const existingField = addedFields.get(id); | ||
if (!existingField) { | ||
throw new errors_1.FormulaFieldNotFoundError(id); | ||
} | ||
existingField.value = value; | ||
if (calculate) { | ||
existingField.calculate = calculate; | ||
} | ||
else { | ||
existingField.calculate = undefined; | ||
} | ||
for (const f of existingField.incomingNeighbors) { | ||
const parentField = addedFields.get(f); | ||
fieldGraph.removeEdge(parentField, existingField); | ||
} | ||
const changes = onFieldChanged(existingField, dependencies); | ||
const possiblyTouchedFields = getPossibleTouchedFieldsOnNodeChange(existingField); | ||
possiblyTouchedFields.delete(existingField.id); | ||
computeRangeEditValueChanges(possiblyTouchedFields, changes); | ||
if (changes.length) { | ||
onChange(changes); | ||
} | ||
}, | ||
addField: ({ id, value, dependencies, calculate }) => { | ||
@@ -52,6 +138,3 @@ if (addedFields.has(id)) { | ||
} | ||
const missingFields = dependencies.filter(d => !addedFields.has(d)); | ||
if (missingFields.length > 0) { | ||
throw new errors_1.FormulaFieldDependencyError(id, missingFields); | ||
} | ||
checkFields(id, dependencies); | ||
const node = new fast_graph_1.Node(id, value); | ||
@@ -62,25 +145,6 @@ if (calculate) { | ||
fieldGraph.addNode(node); | ||
const values = []; | ||
for (const d of dependencies) { | ||
const parentField = addedFields.get(d); | ||
fieldGraph.addEdge(parentField, node); | ||
values.push(parentField.value); | ||
const changes = onFieldChanged(node, dependencies); | ||
if (changes.length) { | ||
onChange(changes); | ||
} | ||
try { | ||
dependencyTree = fieldGraph.kahnTopologicalSort(); | ||
} | ||
catch (ex) { | ||
fieldGraph.removeNode(node); | ||
throw new errors_1.FormulaFieldCircularDependencyError(id); | ||
} | ||
addedFields.set(id, node); | ||
if (dependencies.length && calculate) { | ||
node.value = calculate(...values); | ||
onChange([ | ||
{ | ||
id: node.id, | ||
value: node.value | ||
} | ||
]); | ||
} | ||
}, | ||
@@ -102,23 +166,5 @@ updateFieldsValue: fields => { | ||
possiblyTouchedFields.add(id); | ||
fieldGraph.bfs(n => { | ||
possiblyTouchedFields.add(n.id); | ||
return fast_graph_1.SearchAlgorithmNodeBehavior.continue; | ||
}, node); | ||
getPossibleTouchedFieldsOnNodeChange(node, possiblyTouchedFields); | ||
} | ||
for (const dep of dependencyTree) { | ||
if (!possiblyTouchedFields.has(dep.id)) { | ||
continue; | ||
} | ||
const node = addedFields.get(dep.id); | ||
if (node.calculate) { | ||
node.value = node.calculate(...node.incomingNeighbors.map(n => { | ||
const field = addedFields.get(n); | ||
return field.value; | ||
})); | ||
changes.push({ | ||
id: node.id, | ||
value: node.value | ||
}); | ||
} | ||
} | ||
computeRangeEditValueChanges(possiblyTouchedFields, changes); | ||
onChange(changes); | ||
@@ -125,0 +171,0 @@ } |
@@ -60,2 +60,7 @@ /** | ||
/** | ||
* Edits a formula field in the store. | ||
* @template T - The type of the field value. | ||
*/ | ||
editField: <T>(field: FormulaField<T>) => void; | ||
/** | ||
* Removes a formula field from the store based on its identifier. | ||
@@ -62,0 +67,0 @@ * @returns {string[]} - An array of the field identifiers affected by the removal. |
{ | ||
"name": "formula-store", | ||
"description": " A package to handle formula calculations and dependency management", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"main": "lib/index.js", | ||
@@ -6,0 +6,0 @@ "types": "lib/index.d.ts", |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
49863
288
0