calcfoundry
v0.2.1
Published
A secure CLI tool for evaluating mathematical calculator specifications defined in JSON, with browser compatibility
Downloads
33
Maintainers
Readme
calcfoundry
A secure CLI tool that safely evaluates mathematical calculator specifications defined in JSON. Works in both Node.js and browser environments. Perfect for medical calculators, risk scores, and complex mathematical models.
🚀 Features
- 🔒 Safe Evaluation: Uses whitelisted math.js operations only - no
eval()or arbitrary code execution - 🌐 Universal: Works in Node.js, browsers, and build tools like Vite/Webpack
- 📋 Schema Validation: Validates calculator JSON against strict schema with Ajv
- 🔗 Dependency Resolution: Topological sorting with cycle detection for derived calculations
- 🧪 Built-in Testing: Test framework with tolerance support for validation
- 🏥 Medical Calculator Support: Includes examples like BMI, CHA2DS2-VASc, and KFRE
- ⚡ CLI & Programmatic: Use as CLI tool or import as module
📦 Installation
Global Installation (CLI usage)
npm install -g calcfoundryLocal Installation (project dependency)
npm install calcfoundryBrowser/Frontend Usage
# Works with Vite, Webpack, and other bundlers
npm install calcfoundry// ES6 import (browser/Vite/Webpack)
import { evaluateCalculator } from 'calcfoundry/browser';🎯 Quick Start
CLI Usage
# Run a calculator with custom inputs
calcf run ./sample_calcs/bmi.json --inputs '{"height_cm":180,"weight_kg":75}'
# Run a calculator with test fixture
calcf run ./sample_calcs/bmi.json --fixture "BMI 80kg/170cm"
# Run all tests for a calculator
calcf test ./sample_calcs/bmi.json
# Get help
calcf --helpExample Output
{
"bmi_value": 23.1
}📚 Examples
BMI Calculator
npm run example:bmi
# Output: {"bmi_value": 23.1}CHA2DS2-VASc Score
npm run example:chadsvasc
# Output: {"cha2ds2_vasc_score": 3, "oac_recommendation": "Recommend OAC"}KFRE (Kidney Failure Risk)
npm run example:kfre
# Output: {"risk_5y": 0.0367}🏗️ Calculator JSON Format
Calculators are defined as JSON files with the following structure:
{
"meta": {
"id": "my_calculator",
"title": "My Calculator",
"license": "CC-BY-4.0"
},
"inputs": [
{
"name": "age",
"label": "Age (years)",
"type": "number",
"constraints": {"min": 0, "max": 120, "required": true},
"default": 30
}
],
"constants": [
{"name": "pi", "value": 3.14159}
],
"derived": [
{
"name": "age_squared",
"expr": {"language": "mathjs", "source": "age ^ 2"}
}
],
"outputs": [
{
"name": "result",
"label": "Final Result",
"expr": {"language": "mathjs", "source": "age_squared * pi"},
"round": {"mode": "fixed", "digits": 2}
}
],
"tests": [
{
"name": "Test case 1",
"inputs": {"age": 25},
"expect": [{"name": "result", "equals": 1963.49, "tolerance": 0.01}]
}
],
"version": "0.1.0"
}Supported Field Types
- inputs:
number,integer,boolean,enum,string - Math operations:
+,-,*,/,^, comparison operators - Functions:
abs,min,max,sqrt,exp,log,log10,round,floor,ceil,pow - Conditionals: Ternary operator
condition ? value1 : value2
🔧 Development Scripts
# Run single test
npm test
# Run all example calculators
npm run test:all
# Run examples
npm run example:bmi
npm run example:chadsvasc
npm run example:kfre🔐 Security
- No arbitrary code execution - only whitelisted math.js operations
- AST validation prevents dangerous operations like assignments, imports, array/object access
- Symbol resolution ensures all references resolve to valid inputs/constants/derived values
- Schema validation with strict JSON schema using Ajv
- Dependency cycle detection prevents infinite loops
🏥 Medical Calculator Support
Calcfoundry includes validated implementations of common medical calculators:
- BMI Calculator: Body Mass Index calculation
- CHA2DS2-VASc: Stroke risk assessment for atrial fibrillation
- KFRE: Kidney Failure Risk Equation (4-variable, 5-year)
📖 API Documentation
Node.js Usage (with file I/O)
import { loadCalculator, validateCalculator, evaluateCalculator } from 'calcfoundry';
// Load and validate calculator from file
const calculator = await loadCalculator('./my-calc.json');
const { dependencies } = validateCalculator(calculator);
// Evaluate with inputs
const result = evaluateCalculator(calculator, {age: 30, weight: 70}, dependencies);
console.log(result.outputs);Browser Usage (calculator data as object)
import { evaluateCalculator } from 'calcfoundry/browser';
// Calculator data already loaded as object
const calculatorData = {
meta: { id: "example", title: "Example", license: "MIT" },
inputs: [{ name: "x", type: "number" }],
constants: [],
derived: [],
outputs: [{ name: "result", expr: { source: "x * 2" } }],
tests: [],
version: "1.0"
};
// Direct evaluation (validation included)
const result = evaluateCalculator(calculatorData, { x: 5 });
console.log(result.outputs); // { result: 10 }Advanced Browser Usage
import { validateCalculatorData, evaluateCalculatorData } from 'calcfoundry/browser';
// Separate validation and evaluation steps
const { dependencies } = validateCalculatorData(calculatorData);
const result = evaluateCalculatorData(calculatorData, inputs, dependencies);🤝 Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes and add tests
- Run tests:
npm run test:all - Commit your changes:
git commit -am 'Add feature' - Push to the branch:
git push origin feature-name - Submit a pull request
📄 License
MIT License - see the LICENSE file for details.
🐛 Issues & Support
- Report bugs at: https://github.com/asaabey/calcfoundry-calcengine-npm/issues
- For questions, use GitHub Discussions
- For medical calculator validation, please consult appropriate clinical resources
🏷️ Keywords
medical-calculator, clinical-score, math-evaluation, json-schema, safe-evaluation, mathjs, cli-tool, browser-compatible, isomorphic, bmi, cha2ds2-vasc, kfre
