@bortunac/matx
Version:
Precision-safe math utilities and nested object access for JavaScript.
178 lines (132 loc) • 3.84 kB
Markdown
# Matx
Matx is a precision-safe math utility toolkit with deep object path support, ideal for financial and data aggregation tasks. It enhances JavaScript's native `Math` with precision-aware operations and introduces two object prototype extensions: `.pointer()` for safe nested access and `.scan()` for enumerable iteration.
## 🚀 Installation
```bash
npm install matx
```
## 📦 Usage
### In ES6 module:
```js
import 'matx';
const result = Math.sum(1.1, 2.22); // 3.32
```
### In Browser:
Include the bundled script and use `window.Matx`:
```html
<script src="matx.js" type="module"></script>
or
await import("/path/matx.js");
Math.acm(...)
```
## 🔧 Features
### 🔹 Math Methods
* `Math.sum(...values)` – Accumulates with precision.
* `Math.diff(a, b)` – Subtracts with precision.
* `Math.acm(acmObj, srcObj, keys)` – Accumulate fields from `srcObj` into `acmObj`.
* `Math.acms(...)` – Subtract version of `acm`.
* `Math.acmd(...)` – Divide version of `acm`.
* `Math.float0(x)` – Safe float parse.
* `Math.bytes(x)` – Converts bytes into human-readable units.
* `Math.precision(x, p, type)` – Applies fixed-point rounding.
* `Math.get_precision(x)` – Finds decimal precision of a number.
### 🔸 Object Extensions
#### `.pointer(path[, value])`
Access or set deeply nested properties safely.
```js
const obj = {};
obj.pointer("a.b.c", 42);
console.log(obj); // { a: { b: { c: 42 } } }
```
#### `.scan(callback)`
Iterates key-value pairs like `Array.prototype.map`.
```js
const o = { a: 10, b: 20 };
const keys = o.scan((k, v, i) => `${k}:${v}`);
console.log(keys); // ["a:10", "b:20"]
```
### Array.prototype.having()
This utility adds advanced filtering to arrays:
```js
const COL = [
{ a: 1, b: 2 },
{ a: 2, b: 1 },
{ a: 3, b: 1 },
{ a: 4, b: 5 },
{ a: 5, b: 5 },
{ a: 1, c: { d: 1, e: ["alfa"] } },
{ c: { d: 1, e: ["alfa", "beta"] } }
];
// Filter with object criteria
console.log(COL.having({ b: 5, a: 4 }, { a: [2, 3] }));
// Filter with JS condition expression
console.log(COL.having("${b} > 1 && ${a} > 4"));
// Filter with regex logic
console.log(COL.having("/^5/.test('${b}')"));
// Deep search using $@ pointer notation
console.log(COL.having("$@.c.e[1] !== undefined || $@.a > 2"));
```
## Examples
#### Object `.scan()` with `.pointer` Chaining
```js
const dataset = {
101: { user: { id: 101, name: "Alice", scores: { math: 82 } } },
102: { user: { id: 102, name: "Bob", scores: { math: 91 } } },
103: { user: { id: 103, name: "Charlie", scores: { math: 75 } } }
};
const result = dataset.scan(function (key, value) {
const name = value.pointer("user.name");
const mathScore = value.pointer("user.scores.math");
return `User ${name} scored ${mathScore} in math.`;
});
console.log(result);
// [
// "User Alice scored 82 in math.",
// "User Bob scored 91 in math.",
// "User Charlie scored 75 in math."
// ]
```
#### `Math.acm` Aggregation Example
```js
const acm = { total: 0 };
const items = [
{ total: 10 },
{ total: 25 },
{ total: 5 }
];
Math.acm(acm, items, "total");
console.log(acm); // { total: 40 }
```
#### `Math.acm` with Nested Keys Example
```js
const acm = {};
const records = [
{
year_month: "2024-01",
sales: { online: 100, retail: 200 },
refunds: { online: 3, retail: 4 }
},
{
year_month: "2024-02",
sales: { online: 150, retail: 100 },
refunds: { online: 2, retail: 5 }
}
];
Math.acm(acm, records, [
"sales.online",
"sales.retail",
"refunds.online",
"refunds.retail"
]);
console.log(acm);
// {
// sales: { online: 250, retail: 300 },
// refunds: { online: 5, retail: 9 }
// }
```
### 🔍🧠 Why Matx?
* Zero-dependency
* Precision-safe
* Works with deeply nested objects
* Friendly to financial, scientific, or statistical data models
## 📄 License
MIT