@revisium/formula 0.4.0 → 0.6.0
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/dist/chunk-GOMUE724.cjs +1114 -0
- package/dist/chunk-GOMUE724.cjs.map +1 -0
- package/dist/chunk-LFEHEGBL.js +1086 -0
- package/dist/chunk-LFEHEGBL.js.map +1 -0
- package/dist/editor/index.cjs +4 -13
- package/dist/editor/index.d.cts +1 -1
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +1 -2
- package/dist/formula-spec.cjs +0 -2
- package/dist/formula-spec.cjs.map +1 -1
- package/dist/formula-spec.js +0 -2
- package/dist/formula-spec.js.map +1 -1
- package/dist/{index-JZFJ9oT6.d.cts → index-PFKKFfeI.d.cts} +70 -38
- package/dist/{index-JZFJ9oT6.d.ts → index-PFKKFfeI.d.ts} +70 -38
- package/dist/index.cjs +116 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +109 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-AGBOCJGV.cjs +0 -1266
- package/dist/chunk-AGBOCJGV.cjs.map +0 -1
- package/dist/chunk-FDIJPOVQ.js +0 -1252
- package/dist/chunk-FDIJPOVQ.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -9
- package/dist/chunk-PZ5AY32C.js.map +0 -1
- package/dist/chunk-Q7SFCCGT.cjs +0 -11
- package/dist/chunk-Q7SFCCGT.cjs.map +0 -1
|
@@ -41,7 +41,75 @@ interface FormulaContext {
|
|
|
41
41
|
}
|
|
42
42
|
type FormulaResult = number | string | boolean | null;
|
|
43
43
|
|
|
44
|
-
type ASTNode =
|
|
44
|
+
type ASTNode = NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral | Identifier | RootPath | RelativePath | ContextToken | BinaryOp | UnaryOp | TernaryOp | CallExpression | MemberExpression | IndexExpression | WildcardExpression;
|
|
45
|
+
interface NumberLiteral {
|
|
46
|
+
type: 'NumberLiteral';
|
|
47
|
+
value: number;
|
|
48
|
+
}
|
|
49
|
+
interface StringLiteral {
|
|
50
|
+
type: 'StringLiteral';
|
|
51
|
+
value: string;
|
|
52
|
+
}
|
|
53
|
+
interface BooleanLiteral {
|
|
54
|
+
type: 'BooleanLiteral';
|
|
55
|
+
value: boolean;
|
|
56
|
+
}
|
|
57
|
+
interface NullLiteral {
|
|
58
|
+
type: 'NullLiteral';
|
|
59
|
+
}
|
|
60
|
+
interface Identifier {
|
|
61
|
+
type: 'Identifier';
|
|
62
|
+
name: string;
|
|
63
|
+
}
|
|
64
|
+
interface RootPath {
|
|
65
|
+
type: 'RootPath';
|
|
66
|
+
path: string;
|
|
67
|
+
}
|
|
68
|
+
interface RelativePath {
|
|
69
|
+
type: 'RelativePath';
|
|
70
|
+
path: string;
|
|
71
|
+
}
|
|
72
|
+
interface ContextToken {
|
|
73
|
+
type: 'ContextToken';
|
|
74
|
+
name: string;
|
|
75
|
+
}
|
|
76
|
+
interface BinaryOp {
|
|
77
|
+
type: 'BinaryOp';
|
|
78
|
+
op: string;
|
|
79
|
+
left: ASTNode;
|
|
80
|
+
right: ASTNode;
|
|
81
|
+
}
|
|
82
|
+
interface UnaryOp {
|
|
83
|
+
type: 'UnaryOp';
|
|
84
|
+
op: string;
|
|
85
|
+
argument: ASTNode;
|
|
86
|
+
}
|
|
87
|
+
interface TernaryOp {
|
|
88
|
+
type: 'TernaryOp';
|
|
89
|
+
condition: ASTNode;
|
|
90
|
+
consequent: ASTNode;
|
|
91
|
+
alternate: ASTNode;
|
|
92
|
+
}
|
|
93
|
+
interface CallExpression {
|
|
94
|
+
type: 'CallExpression';
|
|
95
|
+
callee: ASTNode;
|
|
96
|
+
arguments: ASTNode[];
|
|
97
|
+
}
|
|
98
|
+
interface MemberExpression {
|
|
99
|
+
type: 'MemberExpression';
|
|
100
|
+
object: ASTNode;
|
|
101
|
+
property: string;
|
|
102
|
+
}
|
|
103
|
+
interface IndexExpression {
|
|
104
|
+
type: 'IndexExpression';
|
|
105
|
+
object: ASTNode;
|
|
106
|
+
index: ASTNode;
|
|
107
|
+
}
|
|
108
|
+
interface WildcardExpression {
|
|
109
|
+
type: 'WildcardExpression';
|
|
110
|
+
object: ASTNode;
|
|
111
|
+
}
|
|
112
|
+
|
|
45
113
|
interface ParseResult {
|
|
46
114
|
ast: ASTNode;
|
|
47
115
|
dependencies: string[];
|
|
@@ -86,40 +154,4 @@ type SyntaxValidationResult = {
|
|
|
86
154
|
};
|
|
87
155
|
declare function validateFormulaSyntax(expression: string): SyntaxValidationResult;
|
|
88
156
|
|
|
89
|
-
|
|
90
|
-
version: number;
|
|
91
|
-
expression: string;
|
|
92
|
-
}
|
|
93
|
-
interface SchemaProperty {
|
|
94
|
-
type?: string;
|
|
95
|
-
'x-formula'?: XFormulaInput;
|
|
96
|
-
properties?: Record<string, SchemaProperty>;
|
|
97
|
-
items?: SchemaProperty;
|
|
98
|
-
[key: string]: unknown;
|
|
99
|
-
}
|
|
100
|
-
interface JsonSchema {
|
|
101
|
-
type?: string;
|
|
102
|
-
properties?: Record<string, SchemaProperty>;
|
|
103
|
-
items?: SchemaProperty;
|
|
104
|
-
[key: string]: unknown;
|
|
105
|
-
}
|
|
106
|
-
interface ExtractedFormula {
|
|
107
|
-
fieldName: string;
|
|
108
|
-
expression: string;
|
|
109
|
-
fieldType: string;
|
|
110
|
-
}
|
|
111
|
-
declare function extractSchemaFormulas(schema: JsonSchema): ExtractedFormula[];
|
|
112
|
-
|
|
113
|
-
interface FormulaValidationError {
|
|
114
|
-
field: string;
|
|
115
|
-
error: string;
|
|
116
|
-
position?: number;
|
|
117
|
-
}
|
|
118
|
-
interface SchemaValidationResult {
|
|
119
|
-
isValid: boolean;
|
|
120
|
-
errors: FormulaValidationError[];
|
|
121
|
-
}
|
|
122
|
-
declare function validateFormulaAgainstSchema(expression: string, fieldName: string, schema: JsonSchema): FormulaValidationError | null;
|
|
123
|
-
declare function validateSchemaFormulas(schema: JsonSchema): SchemaValidationResult;
|
|
124
|
-
|
|
125
|
-
export { type ASTNode as A, type EvaluateContextOptions as E, type FieldTypes as F, type InferredType as I, type JsonSchema as J, type ParseResult as P, type SyntaxValidationResult as S, type XFormula as X, evaluateWithContext as a, parseExpression as b, type ParsedExpression as c, validateFormulaSyntax as d, evaluate as e, extractSchemaFormulas as f, type ExtractedFormula as g, validateFormulaAgainstSchema as h, inferFormulaType as i, validateSchemaFormulas as j, type FormulaValidationError as k, type SchemaValidationResult as l, type FormulaMinorVersion as m, type FormulaFeature as n, type FormulaAnalysis as o, parseFormula as p, type PathSegment as q, type ParsedPath as r, type PathValidationResult as s, type FormulaContext as t, type FormulaResult as u, validateSyntax as v };
|
|
157
|
+
export { type ASTNode as A, type EvaluateContextOptions as E, type FieldTypes as F, type InferredType as I, type ParseResult as P, type SyntaxValidationResult as S, type XFormula as X, evaluateWithContext as a, parseExpression as b, type ParsedExpression as c, validateFormulaSyntax as d, evaluate as e, type FormulaMinorVersion as f, type FormulaFeature as g, type FormulaAnalysis as h, inferFormulaType as i, type PathSegment as j, type ParsedPath as k, type PathValidationResult as l, type FormulaContext as m, type FormulaResult as n, parseFormula as p, validateSyntax as v };
|
|
@@ -41,7 +41,75 @@ interface FormulaContext {
|
|
|
41
41
|
}
|
|
42
42
|
type FormulaResult = number | string | boolean | null;
|
|
43
43
|
|
|
44
|
-
type ASTNode =
|
|
44
|
+
type ASTNode = NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral | Identifier | RootPath | RelativePath | ContextToken | BinaryOp | UnaryOp | TernaryOp | CallExpression | MemberExpression | IndexExpression | WildcardExpression;
|
|
45
|
+
interface NumberLiteral {
|
|
46
|
+
type: 'NumberLiteral';
|
|
47
|
+
value: number;
|
|
48
|
+
}
|
|
49
|
+
interface StringLiteral {
|
|
50
|
+
type: 'StringLiteral';
|
|
51
|
+
value: string;
|
|
52
|
+
}
|
|
53
|
+
interface BooleanLiteral {
|
|
54
|
+
type: 'BooleanLiteral';
|
|
55
|
+
value: boolean;
|
|
56
|
+
}
|
|
57
|
+
interface NullLiteral {
|
|
58
|
+
type: 'NullLiteral';
|
|
59
|
+
}
|
|
60
|
+
interface Identifier {
|
|
61
|
+
type: 'Identifier';
|
|
62
|
+
name: string;
|
|
63
|
+
}
|
|
64
|
+
interface RootPath {
|
|
65
|
+
type: 'RootPath';
|
|
66
|
+
path: string;
|
|
67
|
+
}
|
|
68
|
+
interface RelativePath {
|
|
69
|
+
type: 'RelativePath';
|
|
70
|
+
path: string;
|
|
71
|
+
}
|
|
72
|
+
interface ContextToken {
|
|
73
|
+
type: 'ContextToken';
|
|
74
|
+
name: string;
|
|
75
|
+
}
|
|
76
|
+
interface BinaryOp {
|
|
77
|
+
type: 'BinaryOp';
|
|
78
|
+
op: string;
|
|
79
|
+
left: ASTNode;
|
|
80
|
+
right: ASTNode;
|
|
81
|
+
}
|
|
82
|
+
interface UnaryOp {
|
|
83
|
+
type: 'UnaryOp';
|
|
84
|
+
op: string;
|
|
85
|
+
argument: ASTNode;
|
|
86
|
+
}
|
|
87
|
+
interface TernaryOp {
|
|
88
|
+
type: 'TernaryOp';
|
|
89
|
+
condition: ASTNode;
|
|
90
|
+
consequent: ASTNode;
|
|
91
|
+
alternate: ASTNode;
|
|
92
|
+
}
|
|
93
|
+
interface CallExpression {
|
|
94
|
+
type: 'CallExpression';
|
|
95
|
+
callee: ASTNode;
|
|
96
|
+
arguments: ASTNode[];
|
|
97
|
+
}
|
|
98
|
+
interface MemberExpression {
|
|
99
|
+
type: 'MemberExpression';
|
|
100
|
+
object: ASTNode;
|
|
101
|
+
property: string;
|
|
102
|
+
}
|
|
103
|
+
interface IndexExpression {
|
|
104
|
+
type: 'IndexExpression';
|
|
105
|
+
object: ASTNode;
|
|
106
|
+
index: ASTNode;
|
|
107
|
+
}
|
|
108
|
+
interface WildcardExpression {
|
|
109
|
+
type: 'WildcardExpression';
|
|
110
|
+
object: ASTNode;
|
|
111
|
+
}
|
|
112
|
+
|
|
45
113
|
interface ParseResult {
|
|
46
114
|
ast: ASTNode;
|
|
47
115
|
dependencies: string[];
|
|
@@ -86,40 +154,4 @@ type SyntaxValidationResult = {
|
|
|
86
154
|
};
|
|
87
155
|
declare function validateFormulaSyntax(expression: string): SyntaxValidationResult;
|
|
88
156
|
|
|
89
|
-
|
|
90
|
-
version: number;
|
|
91
|
-
expression: string;
|
|
92
|
-
}
|
|
93
|
-
interface SchemaProperty {
|
|
94
|
-
type?: string;
|
|
95
|
-
'x-formula'?: XFormulaInput;
|
|
96
|
-
properties?: Record<string, SchemaProperty>;
|
|
97
|
-
items?: SchemaProperty;
|
|
98
|
-
[key: string]: unknown;
|
|
99
|
-
}
|
|
100
|
-
interface JsonSchema {
|
|
101
|
-
type?: string;
|
|
102
|
-
properties?: Record<string, SchemaProperty>;
|
|
103
|
-
items?: SchemaProperty;
|
|
104
|
-
[key: string]: unknown;
|
|
105
|
-
}
|
|
106
|
-
interface ExtractedFormula {
|
|
107
|
-
fieldName: string;
|
|
108
|
-
expression: string;
|
|
109
|
-
fieldType: string;
|
|
110
|
-
}
|
|
111
|
-
declare function extractSchemaFormulas(schema: JsonSchema): ExtractedFormula[];
|
|
112
|
-
|
|
113
|
-
interface FormulaValidationError {
|
|
114
|
-
field: string;
|
|
115
|
-
error: string;
|
|
116
|
-
position?: number;
|
|
117
|
-
}
|
|
118
|
-
interface SchemaValidationResult {
|
|
119
|
-
isValid: boolean;
|
|
120
|
-
errors: FormulaValidationError[];
|
|
121
|
-
}
|
|
122
|
-
declare function validateFormulaAgainstSchema(expression: string, fieldName: string, schema: JsonSchema): FormulaValidationError | null;
|
|
123
|
-
declare function validateSchemaFormulas(schema: JsonSchema): SchemaValidationResult;
|
|
124
|
-
|
|
125
|
-
export { type ASTNode as A, type EvaluateContextOptions as E, type FieldTypes as F, type InferredType as I, type JsonSchema as J, type ParseResult as P, type SyntaxValidationResult as S, type XFormula as X, evaluateWithContext as a, parseExpression as b, type ParsedExpression as c, validateFormulaSyntax as d, evaluate as e, extractSchemaFormulas as f, type ExtractedFormula as g, validateFormulaAgainstSchema as h, inferFormulaType as i, validateSchemaFormulas as j, type FormulaValidationError as k, type SchemaValidationResult as l, type FormulaMinorVersion as m, type FormulaFeature as n, type FormulaAnalysis as o, parseFormula as p, type PathSegment as q, type ParsedPath as r, type PathValidationResult as s, type FormulaContext as t, type FormulaResult as u, validateSyntax as v };
|
|
157
|
+
export { type ASTNode as A, type EvaluateContextOptions as E, type FieldTypes as F, type InferredType as I, type ParseResult as P, type SyntaxValidationResult as S, type XFormula as X, evaluateWithContext as a, parseExpression as b, type ParsedExpression as c, validateFormulaSyntax as d, evaluate as e, type FormulaMinorVersion as f, type FormulaFeature as g, type FormulaAnalysis as h, inferFormulaType as i, type PathSegment as j, type ParsedPath as k, type PathValidationResult as l, type FormulaContext as m, type FormulaResult as n, parseFormula as p, validateSyntax as v };
|
package/dist/index.cjs
CHANGED
|
@@ -1,61 +1,143 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-Q7SFCCGT.cjs');
|
|
3
|
+
var chunkGOMUE724_cjs = require('./chunk-GOMUE724.cjs');
|
|
5
4
|
|
|
5
|
+
// src/dependency-graph.ts
|
|
6
|
+
function buildDependencyGraph(dependencies) {
|
|
7
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
8
|
+
const edges = /* @__PURE__ */ new Map();
|
|
9
|
+
for (const [node, deps] of Object.entries(dependencies)) {
|
|
10
|
+
nodes.add(node);
|
|
11
|
+
edges.set(node, new Set(deps));
|
|
12
|
+
for (const dep of deps) {
|
|
13
|
+
nodes.add(dep);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return { nodes, edges };
|
|
17
|
+
}
|
|
18
|
+
function detectCircularDependencies(graph) {
|
|
19
|
+
const visited = /* @__PURE__ */ new Set();
|
|
20
|
+
const recursionStack = /* @__PURE__ */ new Set();
|
|
21
|
+
const path = [];
|
|
22
|
+
for (const node of graph.nodes) {
|
|
23
|
+
if (!visited.has(node)) {
|
|
24
|
+
const cycle = dfsVisit(node, graph, visited, recursionStack, path);
|
|
25
|
+
if (cycle) {
|
|
26
|
+
return { hasCircular: true, cycle };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return { hasCircular: false, cycle: null };
|
|
31
|
+
}
|
|
32
|
+
function dfsVisit(node, graph, visited, recursionStack, path) {
|
|
33
|
+
visited.add(node);
|
|
34
|
+
recursionStack.add(node);
|
|
35
|
+
path.push(node);
|
|
36
|
+
const deps = graph.edges.get(node);
|
|
37
|
+
if (deps) {
|
|
38
|
+
for (const dep of deps) {
|
|
39
|
+
if (!visited.has(dep)) {
|
|
40
|
+
const cycle = dfsVisit(dep, graph, visited, recursionStack, path);
|
|
41
|
+
if (cycle) {
|
|
42
|
+
return cycle;
|
|
43
|
+
}
|
|
44
|
+
} else if (recursionStack.has(dep)) {
|
|
45
|
+
const cycleStart = path.indexOf(dep);
|
|
46
|
+
return [...path.slice(cycleStart), dep];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
path.pop();
|
|
51
|
+
recursionStack.delete(node);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
function getTopologicalOrder(graph) {
|
|
55
|
+
const circularCheck = detectCircularDependencies(graph);
|
|
56
|
+
if (circularCheck.hasCircular && circularCheck.cycle) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
order: [],
|
|
60
|
+
error: `Circular dependency detected: ${circularCheck.cycle.join(" -> ")}`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const inDegree = initializeInDegree(graph);
|
|
64
|
+
const queue = findZeroInDegreeNodes(inDegree);
|
|
65
|
+
const order = processQueue(queue, graph, inDegree);
|
|
66
|
+
order.reverse();
|
|
67
|
+
return { success: true, order };
|
|
68
|
+
}
|
|
69
|
+
function initializeInDegree(graph) {
|
|
70
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
71
|
+
for (const node of graph.nodes) {
|
|
72
|
+
inDegree.set(node, 0);
|
|
73
|
+
}
|
|
74
|
+
for (const deps of graph.edges.values()) {
|
|
75
|
+
for (const dep of deps) {
|
|
76
|
+
inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return inDegree;
|
|
80
|
+
}
|
|
81
|
+
function findZeroInDegreeNodes(inDegree) {
|
|
82
|
+
const result = [];
|
|
83
|
+
for (const [node, degree] of inDegree) {
|
|
84
|
+
if (degree === 0) {
|
|
85
|
+
result.push(node);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
function processQueue(queue, graph, inDegree) {
|
|
91
|
+
const order = [];
|
|
92
|
+
let head = 0;
|
|
93
|
+
while (head < queue.length) {
|
|
94
|
+
const node = queue[head];
|
|
95
|
+
head++;
|
|
96
|
+
order.push(node);
|
|
97
|
+
const deps = graph.edges.get(node);
|
|
98
|
+
if (deps) {
|
|
99
|
+
for (const dep of deps) {
|
|
100
|
+
const newDegree = (inDegree.get(dep) ?? 0) - 1;
|
|
101
|
+
inDegree.set(dep, newDegree);
|
|
102
|
+
if (newDegree === 0) {
|
|
103
|
+
queue.push(dep);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return order;
|
|
109
|
+
}
|
|
6
110
|
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(exports, "buildDependencyGraph", {
|
|
9
|
-
enumerable: true,
|
|
10
|
-
get: function () { return chunkAGBOCJGV_cjs.buildDependencyGraph; }
|
|
11
|
-
});
|
|
12
|
-
Object.defineProperty(exports, "detectCircularDependencies", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () { return chunkAGBOCJGV_cjs.detectCircularDependencies; }
|
|
15
|
-
});
|
|
16
111
|
Object.defineProperty(exports, "evaluate", {
|
|
17
112
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
113
|
+
get: function () { return chunkGOMUE724_cjs.evaluate; }
|
|
19
114
|
});
|
|
20
115
|
Object.defineProperty(exports, "evaluateWithContext", {
|
|
21
116
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
23
|
-
});
|
|
24
|
-
Object.defineProperty(exports, "extractSchemaFormulas", {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
get: function () { return chunkAGBOCJGV_cjs.extractSchemaFormulas; }
|
|
27
|
-
});
|
|
28
|
-
Object.defineProperty(exports, "getTopologicalOrder", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
get: function () { return chunkAGBOCJGV_cjs.getTopologicalOrder; }
|
|
117
|
+
get: function () { return chunkGOMUE724_cjs.evaluateWithContext; }
|
|
31
118
|
});
|
|
32
119
|
Object.defineProperty(exports, "inferFormulaType", {
|
|
33
120
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
121
|
+
get: function () { return chunkGOMUE724_cjs.inferFormulaType; }
|
|
35
122
|
});
|
|
36
123
|
Object.defineProperty(exports, "parseExpression", {
|
|
37
124
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
125
|
+
get: function () { return chunkGOMUE724_cjs.parseExpression; }
|
|
39
126
|
});
|
|
40
127
|
Object.defineProperty(exports, "parseFormula", {
|
|
41
128
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
43
|
-
});
|
|
44
|
-
Object.defineProperty(exports, "validateFormulaAgainstSchema", {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
get: function () { return chunkAGBOCJGV_cjs.validateFormulaAgainstSchema; }
|
|
129
|
+
get: function () { return chunkGOMUE724_cjs.parseFormula; }
|
|
47
130
|
});
|
|
48
131
|
Object.defineProperty(exports, "validateFormulaSyntax", {
|
|
49
132
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
51
|
-
});
|
|
52
|
-
Object.defineProperty(exports, "validateSchemaFormulas", {
|
|
53
|
-
enumerable: true,
|
|
54
|
-
get: function () { return chunkAGBOCJGV_cjs.validateSchemaFormulas; }
|
|
133
|
+
get: function () { return chunkGOMUE724_cjs.validateFormulaSyntax; }
|
|
55
134
|
});
|
|
56
135
|
Object.defineProperty(exports, "validateSyntax", {
|
|
57
136
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
137
|
+
get: function () { return chunkGOMUE724_cjs.validateSyntax; }
|
|
59
138
|
});
|
|
139
|
+
exports.buildDependencyGraph = buildDependencyGraph;
|
|
140
|
+
exports.detectCircularDependencies = detectCircularDependencies;
|
|
141
|
+
exports.getTopologicalOrder = getTopologicalOrder;
|
|
60
142
|
//# sourceMappingURL=index.cjs.map
|
|
61
143
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
1
|
+
{"version":3,"sources":["../src/dependency-graph.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export interface DependencyGraph {\n nodes: Set<string>;\n edges: Map<string, Set<string>>;\n}\n\nexport interface CircularDependencyResult {\n hasCircular: boolean;\n cycle: string[] | null;\n}\n\nexport interface TopologicalOrderResult {\n success: boolean;\n order: string[];\n error?: string;\n}\n\n/**\n * Build a dependency graph from a dependencies map\n *\n * @param dependencies - Map of node names to their dependencies\n * @returns Dependency graph with nodes and edges\n *\n * @example\n * const graph = buildDependencyGraph({\n * tax: ['price'],\n * total: ['price', 'tax']\n * });\n * // graph.edges.get('tax') = Set(['price'])\n * // graph.edges.get('total') = Set(['price', 'tax'])\n */\nexport function buildDependencyGraph(\n dependencies: Record<string, string[]>,\n): DependencyGraph {\n const nodes = new Set<string>();\n const edges = new Map<string, Set<string>>();\n\n for (const [node, deps] of Object.entries(dependencies)) {\n nodes.add(node);\n edges.set(node, new Set(deps));\n\n for (const dep of deps) {\n nodes.add(dep);\n }\n }\n\n return { nodes, edges };\n}\n\n/**\n * Detect first circular dependency in a dependency graph\n *\n * @param graph - Dependency graph\n * @returns Result with detected cycle (null if no cycle)\n *\n * @example\n * detectCircularDependencies(graph)\n * // { hasCircular: true, cycle: ['a', 'b', 'c', 'a'] }\n */\nexport function detectCircularDependencies(\n graph: DependencyGraph,\n): CircularDependencyResult {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const path: string[] = [];\n\n for (const node of graph.nodes) {\n if (!visited.has(node)) {\n const cycle = dfsVisit(node, graph, visited, recursionStack, path);\n if (cycle) {\n return { hasCircular: true, cycle };\n }\n }\n }\n\n return { hasCircular: false, cycle: null };\n}\n\nfunction dfsVisit(\n node: string,\n graph: DependencyGraph,\n visited: Set<string>,\n recursionStack: Set<string>,\n path: string[],\n): string[] | null {\n visited.add(node);\n recursionStack.add(node);\n path.push(node);\n\n const deps = graph.edges.get(node);\n if (deps) {\n for (const dep of deps) {\n if (!visited.has(dep)) {\n const cycle = dfsVisit(dep, graph, visited, recursionStack, path);\n if (cycle) {\n return cycle;\n }\n } else if (recursionStack.has(dep)) {\n const cycleStart = path.indexOf(dep);\n return [...path.slice(cycleStart), dep];\n }\n }\n }\n\n path.pop();\n recursionStack.delete(node);\n return null;\n}\n\n/**\n * Get topological order for formula evaluation\n *\n * @param graph - Dependency graph\n * @returns Ordered list of field names for evaluation\n *\n * @example\n * getTopologicalOrder(graph)\n * // { success: true, order: ['price', 'tax', 'total'] }\n */\nexport function getTopologicalOrder(\n graph: DependencyGraph,\n): TopologicalOrderResult {\n const circularCheck = detectCircularDependencies(graph);\n if (circularCheck.hasCircular && circularCheck.cycle) {\n return {\n success: false,\n order: [],\n error: `Circular dependency detected: ${circularCheck.cycle.join(' -> ')}`,\n };\n }\n\n const inDegree = initializeInDegree(graph);\n const queue = findZeroInDegreeNodes(inDegree);\n const order = processQueue(queue, graph, inDegree);\n\n order.reverse();\n return { success: true, order };\n}\n\nfunction initializeInDegree(graph: DependencyGraph): Map<string, number> {\n const inDegree = new Map<string, number>();\n\n for (const node of graph.nodes) {\n inDegree.set(node, 0);\n }\n\n for (const deps of graph.edges.values()) {\n for (const dep of deps) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n\n return inDegree;\n}\n\nfunction findZeroInDegreeNodes(inDegree: Map<string, number>): string[] {\n const result: string[] = [];\n for (const [node, degree] of inDegree) {\n if (degree === 0) {\n result.push(node);\n }\n }\n return result;\n}\n\nfunction processQueue(\n queue: string[],\n graph: DependencyGraph,\n inDegree: Map<string, number>,\n): string[] {\n const order: string[] = [];\n let head = 0;\n\n while (head < queue.length) {\n const node = queue[head]!;\n head++;\n order.push(node);\n\n const deps = graph.edges.get(node);\n if (deps) {\n for (const dep of deps) {\n const newDegree = (inDegree.get(dep) ?? 0) - 1;\n inDegree.set(dep, newDegree);\n if (newDegree === 0) {\n queue.push(dep);\n }\n }\n }\n }\n\n return order;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ASTNode, E as EvaluateContextOptions,
|
|
1
|
+
export { A as ASTNode, E as EvaluateContextOptions, F as FieldTypes, h as FormulaAnalysis, m as FormulaContext, g as FormulaFeature, f as FormulaMinorVersion, n as FormulaResult, I as InferredType, P as ParseResult, c as ParsedExpression, k as ParsedPath, j as PathSegment, l as PathValidationResult, S as SyntaxValidationResult, X as XFormula, e as evaluate, a as evaluateWithContext, i as inferFormulaType, b as parseExpression, p as parseFormula, d as validateFormulaSyntax, v as validateSyntax } from './index-PFKKFfeI.cjs';
|
|
2
2
|
|
|
3
3
|
interface DependencyGraph {
|
|
4
4
|
nodes: Set<string>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ASTNode, E as EvaluateContextOptions,
|
|
1
|
+
export { A as ASTNode, E as EvaluateContextOptions, F as FieldTypes, h as FormulaAnalysis, m as FormulaContext, g as FormulaFeature, f as FormulaMinorVersion, n as FormulaResult, I as InferredType, P as ParseResult, c as ParsedExpression, k as ParsedPath, j as PathSegment, l as PathValidationResult, S as SyntaxValidationResult, X as XFormula, e as evaluate, a as evaluateWithContext, i as inferFormulaType, b as parseExpression, p as parseFormula, d as validateFormulaSyntax, v as validateSyntax } from './index-PFKKFfeI.js';
|
|
2
2
|
|
|
3
3
|
interface DependencyGraph {
|
|
4
4
|
nodes: Set<string>;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,111 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
1
|
+
export { evaluate, evaluateWithContext, inferFormulaType, parseExpression, parseFormula, validateFormulaSyntax, validateSyntax } from './chunk-LFEHEGBL.js';
|
|
2
|
+
|
|
3
|
+
// src/dependency-graph.ts
|
|
4
|
+
function buildDependencyGraph(dependencies) {
|
|
5
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
6
|
+
const edges = /* @__PURE__ */ new Map();
|
|
7
|
+
for (const [node, deps] of Object.entries(dependencies)) {
|
|
8
|
+
nodes.add(node);
|
|
9
|
+
edges.set(node, new Set(deps));
|
|
10
|
+
for (const dep of deps) {
|
|
11
|
+
nodes.add(dep);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return { nodes, edges };
|
|
15
|
+
}
|
|
16
|
+
function detectCircularDependencies(graph) {
|
|
17
|
+
const visited = /* @__PURE__ */ new Set();
|
|
18
|
+
const recursionStack = /* @__PURE__ */ new Set();
|
|
19
|
+
const path = [];
|
|
20
|
+
for (const node of graph.nodes) {
|
|
21
|
+
if (!visited.has(node)) {
|
|
22
|
+
const cycle = dfsVisit(node, graph, visited, recursionStack, path);
|
|
23
|
+
if (cycle) {
|
|
24
|
+
return { hasCircular: true, cycle };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { hasCircular: false, cycle: null };
|
|
29
|
+
}
|
|
30
|
+
function dfsVisit(node, graph, visited, recursionStack, path) {
|
|
31
|
+
visited.add(node);
|
|
32
|
+
recursionStack.add(node);
|
|
33
|
+
path.push(node);
|
|
34
|
+
const deps = graph.edges.get(node);
|
|
35
|
+
if (deps) {
|
|
36
|
+
for (const dep of deps) {
|
|
37
|
+
if (!visited.has(dep)) {
|
|
38
|
+
const cycle = dfsVisit(dep, graph, visited, recursionStack, path);
|
|
39
|
+
if (cycle) {
|
|
40
|
+
return cycle;
|
|
41
|
+
}
|
|
42
|
+
} else if (recursionStack.has(dep)) {
|
|
43
|
+
const cycleStart = path.indexOf(dep);
|
|
44
|
+
return [...path.slice(cycleStart), dep];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
path.pop();
|
|
49
|
+
recursionStack.delete(node);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function getTopologicalOrder(graph) {
|
|
53
|
+
const circularCheck = detectCircularDependencies(graph);
|
|
54
|
+
if (circularCheck.hasCircular && circularCheck.cycle) {
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
order: [],
|
|
58
|
+
error: `Circular dependency detected: ${circularCheck.cycle.join(" -> ")}`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const inDegree = initializeInDegree(graph);
|
|
62
|
+
const queue = findZeroInDegreeNodes(inDegree);
|
|
63
|
+
const order = processQueue(queue, graph, inDegree);
|
|
64
|
+
order.reverse();
|
|
65
|
+
return { success: true, order };
|
|
66
|
+
}
|
|
67
|
+
function initializeInDegree(graph) {
|
|
68
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
69
|
+
for (const node of graph.nodes) {
|
|
70
|
+
inDegree.set(node, 0);
|
|
71
|
+
}
|
|
72
|
+
for (const deps of graph.edges.values()) {
|
|
73
|
+
for (const dep of deps) {
|
|
74
|
+
inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return inDegree;
|
|
78
|
+
}
|
|
79
|
+
function findZeroInDegreeNodes(inDegree) {
|
|
80
|
+
const result = [];
|
|
81
|
+
for (const [node, degree] of inDegree) {
|
|
82
|
+
if (degree === 0) {
|
|
83
|
+
result.push(node);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function processQueue(queue, graph, inDegree) {
|
|
89
|
+
const order = [];
|
|
90
|
+
let head = 0;
|
|
91
|
+
while (head < queue.length) {
|
|
92
|
+
const node = queue[head];
|
|
93
|
+
head++;
|
|
94
|
+
order.push(node);
|
|
95
|
+
const deps = graph.edges.get(node);
|
|
96
|
+
if (deps) {
|
|
97
|
+
for (const dep of deps) {
|
|
98
|
+
const newDegree = (inDegree.get(dep) ?? 0) - 1;
|
|
99
|
+
inDegree.set(dep, newDegree);
|
|
100
|
+
if (newDegree === 0) {
|
|
101
|
+
queue.push(dep);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return order;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { buildDependencyGraph, detectCircularDependencies, getTopologicalOrder };
|
|
3
110
|
//# sourceMappingURL=index.js.map
|
|
4
111
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/dependency-graph.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export interface DependencyGraph {\n nodes: Set<string>;\n edges: Map<string, Set<string>>;\n}\n\nexport interface CircularDependencyResult {\n hasCircular: boolean;\n cycle: string[] | null;\n}\n\nexport interface TopologicalOrderResult {\n success: boolean;\n order: string[];\n error?: string;\n}\n\n/**\n * Build a dependency graph from a dependencies map\n *\n * @param dependencies - Map of node names to their dependencies\n * @returns Dependency graph with nodes and edges\n *\n * @example\n * const graph = buildDependencyGraph({\n * tax: ['price'],\n * total: ['price', 'tax']\n * });\n * // graph.edges.get('tax') = Set(['price'])\n * // graph.edges.get('total') = Set(['price', 'tax'])\n */\nexport function buildDependencyGraph(\n dependencies: Record<string, string[]>,\n): DependencyGraph {\n const nodes = new Set<string>();\n const edges = new Map<string, Set<string>>();\n\n for (const [node, deps] of Object.entries(dependencies)) {\n nodes.add(node);\n edges.set(node, new Set(deps));\n\n for (const dep of deps) {\n nodes.add(dep);\n }\n }\n\n return { nodes, edges };\n}\n\n/**\n * Detect first circular dependency in a dependency graph\n *\n * @param graph - Dependency graph\n * @returns Result with detected cycle (null if no cycle)\n *\n * @example\n * detectCircularDependencies(graph)\n * // { hasCircular: true, cycle: ['a', 'b', 'c', 'a'] }\n */\nexport function detectCircularDependencies(\n graph: DependencyGraph,\n): CircularDependencyResult {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const path: string[] = [];\n\n for (const node of graph.nodes) {\n if (!visited.has(node)) {\n const cycle = dfsVisit(node, graph, visited, recursionStack, path);\n if (cycle) {\n return { hasCircular: true, cycle };\n }\n }\n }\n\n return { hasCircular: false, cycle: null };\n}\n\nfunction dfsVisit(\n node: string,\n graph: DependencyGraph,\n visited: Set<string>,\n recursionStack: Set<string>,\n path: string[],\n): string[] | null {\n visited.add(node);\n recursionStack.add(node);\n path.push(node);\n\n const deps = graph.edges.get(node);\n if (deps) {\n for (const dep of deps) {\n if (!visited.has(dep)) {\n const cycle = dfsVisit(dep, graph, visited, recursionStack, path);\n if (cycle) {\n return cycle;\n }\n } else if (recursionStack.has(dep)) {\n const cycleStart = path.indexOf(dep);\n return [...path.slice(cycleStart), dep];\n }\n }\n }\n\n path.pop();\n recursionStack.delete(node);\n return null;\n}\n\n/**\n * Get topological order for formula evaluation\n *\n * @param graph - Dependency graph\n * @returns Ordered list of field names for evaluation\n *\n * @example\n * getTopologicalOrder(graph)\n * // { success: true, order: ['price', 'tax', 'total'] }\n */\nexport function getTopologicalOrder(\n graph: DependencyGraph,\n): TopologicalOrderResult {\n const circularCheck = detectCircularDependencies(graph);\n if (circularCheck.hasCircular && circularCheck.cycle) {\n return {\n success: false,\n order: [],\n error: `Circular dependency detected: ${circularCheck.cycle.join(' -> ')}`,\n };\n }\n\n const inDegree = initializeInDegree(graph);\n const queue = findZeroInDegreeNodes(inDegree);\n const order = processQueue(queue, graph, inDegree);\n\n order.reverse();\n return { success: true, order };\n}\n\nfunction initializeInDegree(graph: DependencyGraph): Map<string, number> {\n const inDegree = new Map<string, number>();\n\n for (const node of graph.nodes) {\n inDegree.set(node, 0);\n }\n\n for (const deps of graph.edges.values()) {\n for (const dep of deps) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n\n return inDegree;\n}\n\nfunction findZeroInDegreeNodes(inDegree: Map<string, number>): string[] {\n const result: string[] = [];\n for (const [node, degree] of inDegree) {\n if (degree === 0) {\n result.push(node);\n }\n }\n return result;\n}\n\nfunction processQueue(\n queue: string[],\n graph: DependencyGraph,\n inDegree: Map<string, number>,\n): string[] {\n const order: string[] = [];\n let head = 0;\n\n while (head < queue.length) {\n const node = queue[head]!;\n head++;\n order.push(node);\n\n const deps = graph.edges.get(node);\n if (deps) {\n for (const dep of deps) {\n const newDegree = (inDegree.get(dep) ?? 0) - 1;\n inDegree.set(dep, newDegree);\n if (newDegree === 0) {\n queue.push(dep);\n }\n }\n }\n }\n\n return order;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revisium/formula",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Formula expression parser and evaluator for Revisium",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"formula",
|
|
@@ -104,6 +104,6 @@
|
|
|
104
104
|
"access": "public"
|
|
105
105
|
},
|
|
106
106
|
"dependencies": {
|
|
107
|
-
"
|
|
107
|
+
"ohm-js": "^17.3.0"
|
|
108
108
|
}
|
|
109
109
|
}
|