exprify 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -33
- package/dist/exprify.cjs.js +671 -4
- package/dist/exprify.cjs.js.map +1 -1
- package/dist/exprify.esm.js +671 -4
- package/dist/exprify.esm.js.map +1 -1
- package/dist/exprify.js +672 -5
- package/dist/exprify.js.map +1 -1
- package/dist/exprify.min.js +2 -2
- package/dist/exprify.min.js.map +1 -1
- package/docs/README.md +34 -0
- package/docs/assets/css/style.scss +4 -0
- package/docs/tokenType.txt +21 -0
- package/package.json +1 -1
- package/.gitattributes +0 -2
- package/.github/workflows/ci.yml +0 -40
- package/.github/workflows/npm-publish.yml +0 -38
- package/.github/workflows/security-audit.yml +0 -34
- package/CHANGELOG.md +0 -11
- package/doc/tokenType.txt +0 -48
- package/rollup.config.js +0 -80
- package/src/assets/capture.jpg +0 -0
- package/src/core/Exprify.js +0 -140
- package/src/core/context.js +0 -30
- package/src/function/executor.js +0 -64
- package/src/function/internal.js +0 -270
- package/src/function/registry.js +0 -68
- package/src/index.js +0 -2
- package/src/math/operations.js +0 -38
- package/src/parser/astBuild.js +0 -508
- package/src/parser/evaluator.js +0 -430
- package/src/parser/tokenizer.js +0 -399
- package/src/utils/globalUnits.js +0 -217
- package/src/utils/store.js +0 -178
- package/src/variables/store.js +0 -75
- package/test/browser.html +0 -23
- package/test/exprify.test.js +0 -140
package/docs/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Exprify Docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exprify Docs
|
|
7
|
+
|
|
8
|
+
Exprify is a JavaScript expression parser and evaluator for math-heavy apps.
|
|
9
|
+
|
|
10
|
+
## Highlights
|
|
11
|
+
|
|
12
|
+
- arithmetic, precedence, bigint, and booleans
|
|
13
|
+
- variables, assignments, and inline functions
|
|
14
|
+
- unit conversion
|
|
15
|
+
- matrices and linear algebra helpers
|
|
16
|
+
- complex numbers
|
|
17
|
+
- symbolic helpers like `simplify`, `derivative`, and `rationalize`
|
|
18
|
+
|
|
19
|
+
## Quick Example
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import Exprify from "exprify";
|
|
23
|
+
|
|
24
|
+
const expr = new Exprify();
|
|
25
|
+
|
|
26
|
+
expr.evaluate("hyp(a, b) = sqrt(a ^ 2 + b ^ 2)");
|
|
27
|
+
console.log(expr.evaluate("hyp(3, 4)"));
|
|
28
|
+
// 5
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## References
|
|
32
|
+
|
|
33
|
+
- [Project README](../README.md)
|
|
34
|
+
- [Token Type Notes](./tokenType.txt)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Token notes for Exprify
|
|
2
|
+
|
|
3
|
+
- Number
|
|
4
|
+
- BigInt
|
|
5
|
+
- Boolean
|
|
6
|
+
- String
|
|
7
|
+
- Identifier
|
|
8
|
+
- Function
|
|
9
|
+
- Operator
|
|
10
|
+
- UnaryOperator
|
|
11
|
+
- Keyword
|
|
12
|
+
- Unit
|
|
13
|
+
- NumberWithUnit
|
|
14
|
+
- ImaginaryLiteral
|
|
15
|
+
- Parenthesis
|
|
16
|
+
- ArrayStart / ArrayEnd
|
|
17
|
+
- BlockStart / BlockEnd
|
|
18
|
+
- Comma
|
|
19
|
+
- Semicolon
|
|
20
|
+
- Colon
|
|
21
|
+
- Dot
|
package/package.json
CHANGED
package/.gitattributes
DELETED
package/.github/workflows/ci.yml
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
- master
|
|
8
|
-
pull_request:
|
|
9
|
-
branches:
|
|
10
|
-
- main
|
|
11
|
-
- master
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
test:
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version:
|
|
20
|
-
- 20
|
|
21
|
-
- 22
|
|
22
|
-
|
|
23
|
-
steps:
|
|
24
|
-
- name: Checkout repository
|
|
25
|
-
uses: actions/checkout@v4
|
|
26
|
-
|
|
27
|
-
- name: Setup Node.js
|
|
28
|
-
uses: actions/setup-node@v4
|
|
29
|
-
with:
|
|
30
|
-
node-version: ${{ matrix.node-version }}
|
|
31
|
-
cache: npm
|
|
32
|
-
|
|
33
|
-
- name: Install dependencies
|
|
34
|
-
run: npm ci
|
|
35
|
-
|
|
36
|
-
- name: Build package
|
|
37
|
-
run: npm run build
|
|
38
|
-
|
|
39
|
-
- name: Run tests
|
|
40
|
-
run: npm test
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
name: Publish Package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types:
|
|
6
|
-
- published
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
publish:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
permissions:
|
|
13
|
-
contents: read
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
- name: Checkout repository
|
|
17
|
-
uses: actions/checkout@v4
|
|
18
|
-
|
|
19
|
-
- name: Setup Node.js
|
|
20
|
-
uses: actions/setup-node@v4
|
|
21
|
-
with:
|
|
22
|
-
node-version: 22
|
|
23
|
-
registry-url: https://registry.npmjs.org/
|
|
24
|
-
cache: npm
|
|
25
|
-
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: npm ci
|
|
28
|
-
|
|
29
|
-
- name: Build package
|
|
30
|
-
run: npm run build
|
|
31
|
-
|
|
32
|
-
- name: Run tests
|
|
33
|
-
run: npm test
|
|
34
|
-
|
|
35
|
-
- name: Publish to npm
|
|
36
|
-
run: npm publish
|
|
37
|
-
env:
|
|
38
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
name: Security Audit
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
- master
|
|
8
|
-
pull_request:
|
|
9
|
-
branches:
|
|
10
|
-
- main
|
|
11
|
-
- master
|
|
12
|
-
schedule:
|
|
13
|
-
- cron: "0 6 * * 1"
|
|
14
|
-
workflow_dispatch:
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
audit:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
|
|
20
|
-
steps:
|
|
21
|
-
- name: Checkout repository
|
|
22
|
-
uses: actions/checkout@v4
|
|
23
|
-
|
|
24
|
-
- name: Setup Node.js
|
|
25
|
-
uses: actions/setup-node@v4
|
|
26
|
-
with:
|
|
27
|
-
node-version: 22
|
|
28
|
-
cache: npm
|
|
29
|
-
|
|
30
|
-
- name: Install dependencies
|
|
31
|
-
run: npm ci
|
|
32
|
-
|
|
33
|
-
- name: Run npm audit
|
|
34
|
-
run: npm audit --audit-level=high
|
package/CHANGELOG.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on Keep a Changelog, and this project follows semantic versioning.
|
|
6
|
-
|
|
7
|
-
## [1.0.1] - 2026-04-05
|
|
8
|
-
|
|
9
|
-
### Fixed
|
|
10
|
-
- Corrected the import path in `src/index.js` to match the actual filename casing of `src/core/Exprify.js`.
|
|
11
|
-
- Resolved a cross-platform build issue where Rollup failed on Linux-based CI environments because of case-sensitive path resolution.
|
package/doc/tokenType.txt
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
ALL TOKEN TYPES (FINAL DESIGN)
|
|
2
|
-
|
|
3
|
-
// LITERALS
|
|
4
|
-
{ type: "Number", value: 10 }
|
|
5
|
-
{ type: "BigInt", value: 10n }
|
|
6
|
-
{ type: "Boolean", value: true }
|
|
7
|
-
{ type: "String", value: "hello" }
|
|
8
|
-
|
|
9
|
-
{ type: "Unit", value: "cm" }
|
|
10
|
-
{ type: "NumberWithUnit", value: 12.7, unit: "cm" }
|
|
11
|
-
{ type: "UnknownUnit", value: 5, unit: "abc" }
|
|
12
|
-
|
|
13
|
-
// IDENTIFIERS
|
|
14
|
-
{ type: "Identifier", value: "x" }
|
|
15
|
-
|
|
16
|
-
// FUNCTIONS
|
|
17
|
-
{ type: "Function", value: "max" }
|
|
18
|
-
|
|
19
|
-
// OPERATORS
|
|
20
|
-
{ type: "Operator", value: "+" }
|
|
21
|
-
{ type: "Operator", value: ">=" }
|
|
22
|
-
{ type: "Operator", value: "&&" }
|
|
23
|
-
{ type: "Operator", value: "|>" }
|
|
24
|
-
|
|
25
|
-
// UNARY
|
|
26
|
-
{ type: "UnaryOperator", value: "-" }
|
|
27
|
-
{ type: "UnaryOperator", value: "!" }
|
|
28
|
-
|
|
29
|
-
// LOGIC / TERNARY
|
|
30
|
-
{ type: "Ternary", value: "?" }
|
|
31
|
-
{ type: "Ternary", value: ":" }
|
|
32
|
-
|
|
33
|
-
// STRUCTURE
|
|
34
|
-
{ type: "Parenthesis", value: "(" }
|
|
35
|
-
{ type: "Parenthesis", value: ")" }
|
|
36
|
-
{ type: "ArrayStart" }
|
|
37
|
-
{ type: "ArrayEnd" }
|
|
38
|
-
{ type: "BlockStart" }
|
|
39
|
-
{ type: "BlockEnd" }
|
|
40
|
-
{ type: "Colon" }
|
|
41
|
-
{ type: "Comma" }
|
|
42
|
-
{ type: "Dot" }
|
|
43
|
-
|
|
44
|
-
// KEYWORDS
|
|
45
|
-
{ type: "Keyword", value: "to" }
|
|
46
|
-
{ type: "Keyword", value: "if" }
|
|
47
|
-
|
|
48
|
-
|
package/rollup.config.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
|
|
4
|
-
import resolve from "@rollup/plugin-node-resolve";
|
|
5
|
-
import commonjs from "@rollup/plugin-commonjs";
|
|
6
|
-
|
|
7
|
-
import terser from "@rollup/plugin-terser";
|
|
8
|
-
import pkg from "./package.json";
|
|
9
|
-
|
|
10
|
-
const short_banner = `/*! ${pkg.name} v${pkg.version} | * (c) ${new Date().getFullYear()} ${pkg.author} and contributors | ${pkg.license} License*/`;
|
|
11
|
-
|
|
12
|
-
const banner = `/*!
|
|
13
|
-
* ${pkg.name} v${pkg.version}
|
|
14
|
-
* (c) ${new Date().getFullYear()} ${pkg.author} and other contributors
|
|
15
|
-
*
|
|
16
|
-
* Released under the ${pkg.license} License
|
|
17
|
-
* Date: ${new Date().toISOString().split('T')[0]}
|
|
18
|
-
*/`;
|
|
19
|
-
|
|
20
|
-
function removeComment() {
|
|
21
|
-
return {
|
|
22
|
-
name: "remove-sourcemap-comment",
|
|
23
|
-
writeBundle(outputOptions, bundle) {
|
|
24
|
-
for (const fileName in bundle) {
|
|
25
|
-
if (fileName.endsWith(".js")) {
|
|
26
|
-
const filePath = path.join(
|
|
27
|
-
outputOptions.dir || path.dirname(outputOptions.file),
|
|
28
|
-
fileName
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
let code = fs.readFileSync(filePath, "utf-8");
|
|
32
|
-
|
|
33
|
-
code = code.replace(/\/\/# sourceMappingURL=.*$/gm, "");
|
|
34
|
-
|
|
35
|
-
fs.writeFileSync(filePath, code);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export default [
|
|
43
|
-
{
|
|
44
|
-
input: "src/index.js",
|
|
45
|
-
output: [
|
|
46
|
-
{
|
|
47
|
-
file: "dist/exprify.esm.js",
|
|
48
|
-
format: "esm",
|
|
49
|
-
sourcemap: true
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
file: "dist/exprify.cjs.js",
|
|
53
|
-
format: "cjs",
|
|
54
|
-
sourcemap: true,
|
|
55
|
-
exports: "default"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
file: "dist/exprify.js",
|
|
59
|
-
format: "umd",
|
|
60
|
-
name: "Exprify",
|
|
61
|
-
banner: banner,
|
|
62
|
-
sourcemap: true,
|
|
63
|
-
indent: true,
|
|
64
|
-
exports: "default"
|
|
65
|
-
}
|
|
66
|
-
],
|
|
67
|
-
plugins: [resolve(), commonjs(), removeComment()]
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
input: "src/index.js",
|
|
71
|
-
output: {
|
|
72
|
-
file: "dist/exprify.min.js",
|
|
73
|
-
format: "umd",
|
|
74
|
-
name: "Exprify",
|
|
75
|
-
sourcemap: true,
|
|
76
|
-
banner: short_banner
|
|
77
|
-
},
|
|
78
|
-
plugins: [resolve(), commonjs(), terser(), removeComment()]
|
|
79
|
-
}
|
|
80
|
-
];
|
package/src/assets/capture.jpg
DELETED
|
Binary file
|
package/src/core/Exprify.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { tokenize } from "../parser/tokenizer.js";
|
|
2
|
-
// import { infixToPostfix } from "../parser/infixToPostfix.js";
|
|
3
|
-
import { evaluateAST } from "../parser/evaluator.js";
|
|
4
|
-
import { createContext } from "./context.js";
|
|
5
|
-
import { mathOperations } from "../math/operations.js";
|
|
6
|
-
|
|
7
|
-
import { createUnitsStore } from "../utils/store.js";
|
|
8
|
-
import { globalUnits } from "../utils/globalUnits.js";
|
|
9
|
-
|
|
10
|
-
import { createVarStore } from "../variables/store.js";
|
|
11
|
-
import { createFunctionRegistry } from "../function/registry.js";
|
|
12
|
-
import { internalFunctions } from "../function/internal.js";
|
|
13
|
-
|
|
14
|
-
import { buildAST } from "../parser/astBuild.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
const isComplex = (value) =>
|
|
20
|
-
value && typeof value === "object" && "re" in value && "im" in value;
|
|
21
|
-
|
|
22
|
-
const isUnitValue = (value) =>
|
|
23
|
-
value && typeof value === "object" && "value" in value && "unit" in value;
|
|
24
|
-
|
|
25
|
-
const isMatrix = (value) =>
|
|
26
|
-
Array.isArray(value) && value.length > 0 && value.every(Array.isArray);
|
|
27
|
-
|
|
28
|
-
const formatComplex = (value) => {
|
|
29
|
-
if (!isComplex(value)) return value;
|
|
30
|
-
|
|
31
|
-
const real = value.re;
|
|
32
|
-
const imaginary = Math.abs(value.im);
|
|
33
|
-
const sign = value.im < 0 ? "-" : "+";
|
|
34
|
-
|
|
35
|
-
if (real === 0) {
|
|
36
|
-
if (value.im === 1) return "i";
|
|
37
|
-
if (value.im === -1) return "-i";
|
|
38
|
-
return `${value.im}i`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const imagPart = imaginary === 1 ? "i" : `${imaginary}i`;
|
|
42
|
-
return `${real} ${sign} ${imagPart}`;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const formatResult = (value) => {
|
|
46
|
-
if (isComplex(value)) {
|
|
47
|
-
return formatComplex(value);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (isUnitValue(value)) {
|
|
51
|
-
return `${value.value} ${value.unit}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (isMatrix(value)) {
|
|
55
|
-
return value.map((row) => row.join("\t")).join("\n");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (Array.isArray(value)) {
|
|
59
|
-
return value.join("\n");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return value;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
class exprify {
|
|
66
|
-
constructor() {
|
|
67
|
-
// Shared state
|
|
68
|
-
this.math = mathOperations;
|
|
69
|
-
this.units = createUnitsStore(globalUnits);
|
|
70
|
-
this.functions = createFunctionRegistry(internalFunctions);
|
|
71
|
-
this.variables = createVarStore();
|
|
72
|
-
this._cache = new Map();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
setVariable(name, value) {
|
|
76
|
-
this.variables.set(name, value);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getVariable(name) {
|
|
80
|
-
return this.variables.get(name);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
addFunction(name, fn) {
|
|
84
|
-
this.functions.register(name, fn);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
_createContext() {
|
|
88
|
-
return createContext({
|
|
89
|
-
functions: this.functions,
|
|
90
|
-
variables: this.variables,
|
|
91
|
-
units: this.units,
|
|
92
|
-
evaluate: this.evaluate.bind(this)
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
tokenize(expr) {
|
|
97
|
-
if (typeof expr !== "string") {
|
|
98
|
-
throw new Error("Expression must be a string");
|
|
99
|
-
}
|
|
100
|
-
return tokenize(expr, this._createContext());
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
parse(expr) {
|
|
104
|
-
const tokens = this.tokenize(expr);
|
|
105
|
-
const ast = buildAST(tokens);
|
|
106
|
-
return { tokens, ast };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
evaluate(expr) {
|
|
110
|
-
const { ast } = this.parse(expr);
|
|
111
|
-
return formatResult(evaluateAST(
|
|
112
|
-
ast,
|
|
113
|
-
this._createContext()
|
|
114
|
-
));
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
compile(expr) {
|
|
118
|
-
if (this._cache.has(expr)) {
|
|
119
|
-
return this._cache.get(expr);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const { ast } = this.parse(expr);
|
|
123
|
-
|
|
124
|
-
const compiledFn = (scope = {}) => {
|
|
125
|
-
const baseContext = this._createContext();
|
|
126
|
-
const scopedContext = baseContext.withScope(scope);
|
|
127
|
-
return formatResult(evaluateAST(ast, scopedContext));
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
this._cache.set(expr, compiledFn);
|
|
131
|
-
return compiledFn;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
clearCache() {
|
|
135
|
-
this._cache.clear();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export default exprify;
|
package/src/core/context.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function createContext({ variables, functions, units, evaluate}) {
|
|
2
|
-
if (!variables) throw new Error("Variable store missing");
|
|
3
|
-
if (!functions) throw new Error("Function registry missing");
|
|
4
|
-
if (!units) throw new Error("Units list missing");
|
|
5
|
-
if (!evaluate) throw new Error("evaluate function missing");
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
variables: variables,
|
|
9
|
-
functions: functions,
|
|
10
|
-
units: units,
|
|
11
|
-
evaluate,
|
|
12
|
-
withScope(scope = {}) {
|
|
13
|
-
const tempVars = {
|
|
14
|
-
...variables.all?.(),
|
|
15
|
-
...scope
|
|
16
|
-
};
|
|
17
|
-
return createContext({
|
|
18
|
-
functions: functions,
|
|
19
|
-
evaluate,
|
|
20
|
-
units,
|
|
21
|
-
variables: {
|
|
22
|
-
get: (k) => tempVars[k],
|
|
23
|
-
set: (k, v) => (tempVars[k] = v),
|
|
24
|
-
all: () => tempVars
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
package/src/function/executor.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
export function createFunctionExecutor(fnRegistry, options = {}) {
|
|
2
|
-
if (!fnRegistry) {
|
|
3
|
-
throw new Error("Function registry is required");
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const config = {
|
|
7
|
-
strict: options.strict ?? true
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/* ================= EXECUTE ================= */
|
|
11
|
-
|
|
12
|
-
function execute(name, args = [], context) {
|
|
13
|
-
const fn = fnRegistry.get(name);
|
|
14
|
-
|
|
15
|
-
/* ----- NOT FOUND ----- */
|
|
16
|
-
if (!fn) {
|
|
17
|
-
if (config.strict) {
|
|
18
|
-
throw new Error(`Unknown function: ${name}`);
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/* ----- VALIDATE ARGS ----- */
|
|
24
|
-
if (!Array.isArray(args)) {
|
|
25
|
-
throw new Error(`Arguments for "${name}" must be an array`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* ----- EXECUTE ----- */
|
|
29
|
-
try {
|
|
30
|
-
return fn(...args);
|
|
31
|
-
} catch (err) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Error in function "${name}": ${err.message}`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/* ================= SAFE EXECUTE ================= */
|
|
39
|
-
|
|
40
|
-
function safeExecute(name, args = [], context) {
|
|
41
|
-
try {
|
|
42
|
-
return execute(name, args, context);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
return {
|
|
45
|
-
error: true,
|
|
46
|
-
message: err.message
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* ================= EXISTS ================= */
|
|
52
|
-
|
|
53
|
-
function exists(name) {
|
|
54
|
-
return fnRegistry.has(name);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* ================= API ================= */
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
execute,
|
|
61
|
-
safeExecute,
|
|
62
|
-
exists
|
|
63
|
-
};
|
|
64
|
-
}
|