drools-builder 0.1.2 → 0.1.3
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 +1 -0
- package/dist/index.cjs +129 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +129 -106
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -375,6 +375,7 @@ function resolveRule(input) {
|
|
|
375
375
|
var DroolsFileBuilder = class {
|
|
376
376
|
constructor(name) {
|
|
377
377
|
this._imports = [];
|
|
378
|
+
this._globals = [];
|
|
378
379
|
this._rules = [];
|
|
379
380
|
this._name = name;
|
|
380
381
|
}
|
|
@@ -389,6 +390,17 @@ var DroolsFileBuilder = class {
|
|
|
389
390
|
this._imports.push(className);
|
|
390
391
|
return this;
|
|
391
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Declare a global variable available to all rules in this file.
|
|
395
|
+
* Emits `global type name;` in the DRL header.
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* .global('com.example.AlertService', 'alertService')
|
|
399
|
+
*/
|
|
400
|
+
global(type, name) {
|
|
401
|
+
this._globals.push({ type, name });
|
|
402
|
+
return this;
|
|
403
|
+
}
|
|
392
404
|
/**
|
|
393
405
|
* Add a rule to the file.
|
|
394
406
|
* Accepts a plain Rule object or a RuleBuilder (auto-resolved via .build()).
|
|
@@ -405,6 +417,7 @@ var DroolsFileBuilder = class {
|
|
|
405
417
|
return {
|
|
406
418
|
name: this._name,
|
|
407
419
|
imports: [...this._imports],
|
|
420
|
+
globals: [...this._globals],
|
|
408
421
|
rules: [...this._rules]
|
|
409
422
|
};
|
|
410
423
|
}
|
|
@@ -469,6 +482,114 @@ function rawConsequence(code) {
|
|
|
469
482
|
return { kind: "RawConsequence", code };
|
|
470
483
|
}
|
|
471
484
|
|
|
485
|
+
// src/rule-builder/parser/MetaToDRLTransformer.ts
|
|
486
|
+
function generateConstraint(c) {
|
|
487
|
+
switch (c.kind) {
|
|
488
|
+
case "FieldConstraint":
|
|
489
|
+
return `${c.binding ? `${c.binding} : ` : ""}${c.field} ${c.operator} ${c.value}`;
|
|
490
|
+
case "BindingConstraint":
|
|
491
|
+
return `${c.binding} : ${c.field}`;
|
|
492
|
+
case "RawConstraint":
|
|
493
|
+
return c.expression;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function generateCondition(cond, indent = " ") {
|
|
497
|
+
switch (cond.kind) {
|
|
498
|
+
case "FactPattern": {
|
|
499
|
+
const binding = cond.binding ? `${cond.binding} : ` : "";
|
|
500
|
+
const constraints = cond.constraints.map(generateConstraint).join(", ");
|
|
501
|
+
return `${binding}${cond.factType}( ${constraints} )`;
|
|
502
|
+
}
|
|
503
|
+
case "UnboundPattern": {
|
|
504
|
+
const constraints = cond.constraints.map(generateConstraint).join(", ");
|
|
505
|
+
return `${cond.factType}( ${constraints} )`;
|
|
506
|
+
}
|
|
507
|
+
case "And": {
|
|
508
|
+
const parts = cond.conditions.map((c) => generateCondition(c, indent + " "));
|
|
509
|
+
return `( ${parts.join(`
|
|
510
|
+
${indent} and `)} )`;
|
|
511
|
+
}
|
|
512
|
+
case "Or": {
|
|
513
|
+
const parts = cond.conditions.map((c) => generateCondition(c, indent + " "));
|
|
514
|
+
return `( ${parts.join(`
|
|
515
|
+
${indent} or `)} )`;
|
|
516
|
+
}
|
|
517
|
+
case "Not":
|
|
518
|
+
return `not( ${generateCondition(cond.condition, indent)} )`;
|
|
519
|
+
case "Exists":
|
|
520
|
+
return `exists( ${generateCondition(cond.condition, indent)} )`;
|
|
521
|
+
case "Forall":
|
|
522
|
+
return `forall( ${generateCondition(cond.condition, indent)} )`;
|
|
523
|
+
case "Accumulate": {
|
|
524
|
+
const source = generateCondition(cond.source, indent + " ");
|
|
525
|
+
const fns = cond.functions.map((f) => `${f.binding} : ${f.function}( ${f.argument} )`).join(", ");
|
|
526
|
+
const result = cond.resultConstraint ? `;
|
|
527
|
+
${indent} ${cond.resultConstraint}` : "";
|
|
528
|
+
return `accumulate(
|
|
529
|
+
${indent} ${source};
|
|
530
|
+
${indent} ${fns}${result}
|
|
531
|
+
${indent})`;
|
|
532
|
+
}
|
|
533
|
+
case "From":
|
|
534
|
+
return `${generateCondition(cond.pattern, indent)} from ${cond.expression}`;
|
|
535
|
+
case "Eval":
|
|
536
|
+
return `eval( ${cond.expression} )`;
|
|
537
|
+
case "RawCondition":
|
|
538
|
+
return cond.drl;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
function generateWhenBlock(conditions, indent = " ") {
|
|
542
|
+
const flat = conditions.length === 1 && conditions[0].kind === "And" ? conditions[0].conditions : conditions;
|
|
543
|
+
return flat.map((c) => `${indent}${generateCondition(c, indent)}`).join("\n");
|
|
544
|
+
}
|
|
545
|
+
function generateConsequence(cons, indent = " ") {
|
|
546
|
+
switch (cons.kind) {
|
|
547
|
+
case "ModifyConsequence": {
|
|
548
|
+
const mods = cons.modifications.map((m) => `${m.method}( ${m.args.join(", ")} )`).join(`,
|
|
549
|
+
${indent} `);
|
|
550
|
+
return `modify( ${cons.binding} ) {
|
|
551
|
+
${indent} ${mods}
|
|
552
|
+
${indent}}`;
|
|
553
|
+
}
|
|
554
|
+
case "InsertConsequence":
|
|
555
|
+
return `insert( ${cons.objectExpression} );`;
|
|
556
|
+
case "RetractConsequence":
|
|
557
|
+
return `retract( ${cons.binding} );`;
|
|
558
|
+
case "SetGlobalConsequence":
|
|
559
|
+
return `${cons.expression};`;
|
|
560
|
+
case "RawConsequence":
|
|
561
|
+
return `${cons.code};`;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function generateRule(rule) {
|
|
565
|
+
const lines = [`rule "${rule.name}"`];
|
|
566
|
+
if (rule.salience !== void 0) lines.push(` salience ${rule.salience}`);
|
|
567
|
+
if (rule.agendaGroup !== void 0) lines.push(` agenda-group "${rule.agendaGroup}"`);
|
|
568
|
+
if (rule.ruleFlowGroup !== void 0) lines.push(` ruleflow-group "${rule.ruleFlowGroup}"`);
|
|
569
|
+
if (rule.noLoop) lines.push(" no-loop true");
|
|
570
|
+
if (rule.lockOnActive) lines.push(" lock-on-active true");
|
|
571
|
+
lines.push(" when");
|
|
572
|
+
lines.push(generateWhenBlock(rule.conditions));
|
|
573
|
+
lines.push(" then");
|
|
574
|
+
lines.push(rule.consequences.map((c) => ` ${generateConsequence(c)}`).join("\n"));
|
|
575
|
+
lines.push("end");
|
|
576
|
+
return lines.join("\n");
|
|
577
|
+
}
|
|
578
|
+
var MetaToDRLTransformer = {
|
|
579
|
+
generate(file) {
|
|
580
|
+
const sections = [];
|
|
581
|
+
if (file.imports.length > 0)
|
|
582
|
+
sections.push(file.imports.map((i) => `import ${i};`).join("\n"));
|
|
583
|
+
if (file.globals.length > 0)
|
|
584
|
+
sections.push(file.globals.map((g) => `global ${g.type} ${g.name};`).join("\n"));
|
|
585
|
+
sections.push(file.rules.map(generateRule).join("\n\n"));
|
|
586
|
+
return sections.join("\n\n");
|
|
587
|
+
},
|
|
588
|
+
generateRule(rule) {
|
|
589
|
+
return generateRule(rule);
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
472
593
|
// src/rule-builder/parser/DRLToMetaTransformer.ts
|
|
473
594
|
function indexAtDepth0(text, needle) {
|
|
474
595
|
let depth = 0;
|
|
@@ -569,6 +690,13 @@ function parseImports(drl) {
|
|
|
569
690
|
while ((m = re.exec(drl)) !== null) imports.push(m[1].trim());
|
|
570
691
|
return imports;
|
|
571
692
|
}
|
|
693
|
+
function parseGlobals(drl) {
|
|
694
|
+
const globals = [];
|
|
695
|
+
const re = /^\s*global\s+(\S+)\s+(\S+?)\s*;?$/gm;
|
|
696
|
+
let m;
|
|
697
|
+
while ((m = re.exec(drl)) !== null) globals.push({ type: m[1], name: m[2] });
|
|
698
|
+
return globals;
|
|
699
|
+
}
|
|
572
700
|
function extractRuleBlocks(drl) {
|
|
573
701
|
const blocks = [];
|
|
574
702
|
const re = /\brule\s+"[^"]*"[\s\S]*?\bend\b/g;
|
|
@@ -809,6 +937,7 @@ var DRLToMetaTransformer = {
|
|
|
809
937
|
return {
|
|
810
938
|
name: "parsed",
|
|
811
939
|
imports: parseImports(clean),
|
|
940
|
+
globals: parseGlobals(clean),
|
|
812
941
|
rules: extractRuleBlocks(clean).map((block) => DRLToMetaTransformer.parseRule(block))
|
|
813
942
|
};
|
|
814
943
|
},
|
|
@@ -821,112 +950,6 @@ var DRLToMetaTransformer = {
|
|
|
821
950
|
};
|
|
822
951
|
}
|
|
823
952
|
};
|
|
824
|
-
|
|
825
|
-
// src/rule-builder/parser/MetaToDRLTransformer.ts
|
|
826
|
-
function generateConstraint(c) {
|
|
827
|
-
switch (c.kind) {
|
|
828
|
-
case "FieldConstraint":
|
|
829
|
-
return `${c.binding ? `${c.binding} : ` : ""}${c.field} ${c.operator} ${c.value}`;
|
|
830
|
-
case "BindingConstraint":
|
|
831
|
-
return `${c.binding} : ${c.field}`;
|
|
832
|
-
case "RawConstraint":
|
|
833
|
-
return c.expression;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
function generateCondition(cond, indent = " ") {
|
|
837
|
-
switch (cond.kind) {
|
|
838
|
-
case "FactPattern": {
|
|
839
|
-
const binding = cond.binding ? `${cond.binding} : ` : "";
|
|
840
|
-
const constraints = cond.constraints.map(generateConstraint).join(", ");
|
|
841
|
-
return `${binding}${cond.factType}( ${constraints} )`;
|
|
842
|
-
}
|
|
843
|
-
case "UnboundPattern": {
|
|
844
|
-
const constraints = cond.constraints.map(generateConstraint).join(", ");
|
|
845
|
-
return `${cond.factType}( ${constraints} )`;
|
|
846
|
-
}
|
|
847
|
-
case "And": {
|
|
848
|
-
const parts = cond.conditions.map((c) => generateCondition(c, indent + " "));
|
|
849
|
-
return `( ${parts.join(`
|
|
850
|
-
${indent} and `)} )`;
|
|
851
|
-
}
|
|
852
|
-
case "Or": {
|
|
853
|
-
const parts = cond.conditions.map((c) => generateCondition(c, indent + " "));
|
|
854
|
-
return `( ${parts.join(`
|
|
855
|
-
${indent} or `)} )`;
|
|
856
|
-
}
|
|
857
|
-
case "Not":
|
|
858
|
-
return `not( ${generateCondition(cond.condition, indent)} )`;
|
|
859
|
-
case "Exists":
|
|
860
|
-
return `exists( ${generateCondition(cond.condition, indent)} )`;
|
|
861
|
-
case "Forall":
|
|
862
|
-
return `forall( ${generateCondition(cond.condition, indent)} )`;
|
|
863
|
-
case "Accumulate": {
|
|
864
|
-
const source = generateCondition(cond.source, indent + " ");
|
|
865
|
-
const fns = cond.functions.map((f) => `${f.binding} : ${f.function}( ${f.argument} )`).join(", ");
|
|
866
|
-
const result = cond.resultConstraint ? `;
|
|
867
|
-
${indent} ${cond.resultConstraint}` : "";
|
|
868
|
-
return `accumulate(
|
|
869
|
-
${indent} ${source};
|
|
870
|
-
${indent} ${fns}${result}
|
|
871
|
-
${indent})`;
|
|
872
|
-
}
|
|
873
|
-
case "From":
|
|
874
|
-
return `${generateCondition(cond.pattern, indent)} from ${cond.expression}`;
|
|
875
|
-
case "Eval":
|
|
876
|
-
return `eval( ${cond.expression} )`;
|
|
877
|
-
case "RawCondition":
|
|
878
|
-
return cond.drl;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
function generateWhenBlock(conditions, indent = " ") {
|
|
882
|
-
const flat = conditions.length === 1 && conditions[0].kind === "And" ? conditions[0].conditions : conditions;
|
|
883
|
-
return flat.map((c) => `${indent}${generateCondition(c, indent)}`).join("\n");
|
|
884
|
-
}
|
|
885
|
-
function generateConsequence(cons, indent = " ") {
|
|
886
|
-
switch (cons.kind) {
|
|
887
|
-
case "ModifyConsequence": {
|
|
888
|
-
const mods = cons.modifications.map((m) => `${m.method}( ${m.args.join(", ")} )`).join(`,
|
|
889
|
-
${indent} `);
|
|
890
|
-
return `modify( ${cons.binding} ) {
|
|
891
|
-
${indent} ${mods}
|
|
892
|
-
${indent}}`;
|
|
893
|
-
}
|
|
894
|
-
case "InsertConsequence":
|
|
895
|
-
return `insert( ${cons.objectExpression} );`;
|
|
896
|
-
case "RetractConsequence":
|
|
897
|
-
return `retract( ${cons.binding} );`;
|
|
898
|
-
case "SetGlobalConsequence":
|
|
899
|
-
return `${cons.expression};`;
|
|
900
|
-
case "RawConsequence":
|
|
901
|
-
return `${cons.code};`;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
function generateRule(rule) {
|
|
905
|
-
const lines = [`rule "${rule.name}"`];
|
|
906
|
-
if (rule.salience !== void 0) lines.push(` salience ${rule.salience}`);
|
|
907
|
-
if (rule.agendaGroup !== void 0) lines.push(` agenda-group "${rule.agendaGroup}"`);
|
|
908
|
-
if (rule.ruleFlowGroup !== void 0) lines.push(` ruleflow-group "${rule.ruleFlowGroup}"`);
|
|
909
|
-
if (rule.noLoop) lines.push(" no-loop true");
|
|
910
|
-
if (rule.lockOnActive) lines.push(" lock-on-active true");
|
|
911
|
-
lines.push(" when");
|
|
912
|
-
lines.push(generateWhenBlock(rule.conditions));
|
|
913
|
-
lines.push(" then");
|
|
914
|
-
lines.push(rule.consequences.map((c) => ` ${generateConsequence(c)}`).join("\n"));
|
|
915
|
-
lines.push("end");
|
|
916
|
-
return lines.join("\n");
|
|
917
|
-
}
|
|
918
|
-
var MetaToDRLTransformer = {
|
|
919
|
-
generate(file) {
|
|
920
|
-
const sections = [];
|
|
921
|
-
if (file.imports.length > 0)
|
|
922
|
-
sections.push(file.imports.map((i) => `import ${i};`).join("\n"));
|
|
923
|
-
sections.push(file.rules.map(generateRule).join("\n\n"));
|
|
924
|
-
return sections.join("\n\n");
|
|
925
|
-
},
|
|
926
|
-
generateRule(rule) {
|
|
927
|
-
return generateRule(rule);
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
953
|
export {
|
|
931
954
|
AccumulateBuilder,
|
|
932
955
|
Aggregate,
|