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/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,