api-tests-coverage 1.0.5 → 1.0.6

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.
Files changed (57) hide show
  1. package/dist/dashboard/dist/assets/_basePickBy-CeCjvJWr.js +1 -0
  2. package/dist/dashboard/dist/assets/_baseUniq-DQMeOG5y.js +1 -0
  3. package/dist/dashboard/dist/assets/arc-BDIdECDJ.js +1 -0
  4. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-D2t8Py1B.js +36 -0
  5. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-7B2h6RPh.js +122 -0
  6. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-BJS73w81.js +10 -0
  7. package/dist/dashboard/dist/assets/channel-B5FEo6x8.js +1 -0
  8. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-rMDV_g4i.js +1 -0
  9. package/dist/dashboard/dist/assets/chunk-55IACEB6-H2T0HHMf.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-BIav900j.js +165 -0
  11. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-CL1ZxZeg.js +220 -0
  12. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-BH1h7N7Y.js +15 -0
  13. package/dist/dashboard/dist/assets/chunk-QN33PNHL-Dzk5VCZ3.js +1 -0
  14. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-Z3uL3Vu6.js +1 -0
  15. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-Bk8ko3-5.js +1 -0
  16. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-M4p4DdHs.js +1 -0
  17. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-M4p4DdHs.js +1 -0
  18. package/dist/dashboard/dist/assets/clone-DISkn1y_.js +1 -0
  19. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BbDNIhrI.js +1 -0
  20. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-Niwmlwr0.js +4 -0
  21. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-D6YSgDDJ.js +24 -0
  22. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-BIV3o3EV.js +43 -0
  23. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-B_V6T3Do.js +24 -0
  24. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-Dv8XSfJj.js +60 -0
  25. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-DHVxWNFx.js +162 -0
  26. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-C0zKIcDh.js +267 -0
  27. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-DbNQAtGz.js +65 -0
  28. package/dist/dashboard/dist/assets/graph-BUXAK8S4.js +1 -0
  29. package/dist/dashboard/dist/assets/index-HrRX8fCW.css +1 -0
  30. package/dist/dashboard/dist/assets/index-k7QMCdxo.js +522 -0
  31. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-CbvfFEOs.js +2 -0
  32. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-CHncp1wO.js +139 -0
  33. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-Ct5tvLkE.js +89 -0
  34. package/dist/dashboard/dist/assets/layout-DEw3EHVd.js +1 -0
  35. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-CM92aa9b.js +68 -0
  36. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-Dow8SBXC.js +30 -0
  37. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CHDOoeNa.js +7 -0
  38. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-BdQwEiam.js +64 -0
  39. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-C2tgBc3h.js +10 -0
  40. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-BJapitlJ.js +145 -0
  41. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-CAMqhH5J.js +1 -0
  42. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-DMcei2iB.js +1 -0
  43. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-CgZuzj68.js +61 -0
  44. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-DISZoPlK.js +162 -0
  45. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-WhBuJ91k.js +7 -0
  46. package/dist/dashboard/dist/index.html +2 -2
  47. package/dist/src/index.js +248 -11
  48. package/dist/src/inference/businessRuleInference.d.ts +8 -0
  49. package/dist/src/inference/businessRuleInference.d.ts.map +1 -1
  50. package/dist/src/inference/businessRuleInference.js +52 -0
  51. package/dist/src/inference/routeInference.d.ts +50 -0
  52. package/dist/src/inference/routeInference.d.ts.map +1 -0
  53. package/dist/src/inference/routeInference.js +220 -0
  54. package/dist/src/inference/scanManifest.d.ts +35 -0
  55. package/dist/src/inference/scanManifest.d.ts.map +1 -0
  56. package/dist/src/inference/scanManifest.js +58 -0
  57. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import{s as gi,g as xi,q as Xt,p as di,a as pi,b as fi,_ as n,l as Nt,H as yi,e as mi,y as bi,F as Ct,i as Ai,D as Yt,E as wi,L as Ci,M as Bt,N as Si,K as Wt,O as zt}from"./index-k7QMCdxo.js";var mt=function(){var s=n(function(W,r,u,g){for(u=u||{},g=W.length;g--;u[W[g]]=r);return u},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],e=[1,3],a=[1,5],c=[1,6],d=[1,7],m=[1,5,10,12,14,16,18,19,21,23,34,35,36],b=[1,25],P=[1,26],I=[1,28],R=[1,29],L=[1,30],z=[1,31],F=[1,32],D=[1,33],V=[1,34],f=[1,35],C=[1,36],l=[1,37],M=[1,43],B=[1,42],U=[1,47],X=[1,50],h=[1,10,12,14,16,18,19,21,23,34,35,36],k=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],w=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36,41,42,43,44,45,46,47,48,49,50],S=[1,64],$={trace:n(function(){},"trace"),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,commaSeparatedNumbers:25,SQUARE_BRACES_END:26,NUMBER_WITH_DECIMAL:27,COMMA:28,xAxisData:29,bandData:30,ARROW_DELIMITER:31,commaSeparatedTexts:32,yAxisData:33,NEWLINE:34,SEMI:35,EOF:36,alphaNum:37,STR:38,MD_STR:39,alphaNumToken:40,AMP:41,NUM:42,ALPHA:43,PLUS:44,EQUALS:45,MULT:46,DOT:47,BRKT:48,MINUS:49,UNDERSCORE:50,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",27:"NUMBER_WITH_DECIMAL",28:"COMMA",31:"ARROW_DELIMITER",34:"NEWLINE",35:"SEMI",36:"EOF",38:"STR",39:"MD_STR",41:"AMP",42:"NUM",43:"ALPHA",44:"PLUS",45:"EQUALS",46:"MULT",47:"DOT",48:"BRKT",49:"MINUS",50:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[13,1],[13,2],[13,1],[29,1],[29,3],[30,3],[32,3],[32,1],[15,1],[15,2],[15,1],[33,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[37,1],[37,2],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1]],performAction:n(function(r,u,g,x,A,o,nt){var p=o.length-1;switch(A){case 5:x.setOrientation(o[p]);break;case 9:x.setDiagramTitle(o[p].text.trim());break;case 12:x.setLineData({text:"",type:"text"},o[p]);break;case 13:x.setLineData(o[p-1],o[p]);break;case 14:x.setBarData({text:"",type:"text"},o[p]);break;case 15:x.setBarData(o[p-1],o[p]);break;case 16:this.$=o[p].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=o[p].trim(),x.setAccDescription(this.$);break;case 19:this.$=o[p-1];break;case 20:this.$=[Number(o[p-2]),...o[p]];break;case 21:this.$=[Number(o[p])];break;case 22:x.setXAxisTitle(o[p]);break;case 23:x.setXAxisTitle(o[p-1]);break;case 24:x.setXAxisTitle({type:"text",text:""});break;case 25:x.setXAxisBand(o[p]);break;case 26:x.setXAxisRangeData(Number(o[p-2]),Number(o[p]));break;case 27:this.$=o[p-1];break;case 28:this.$=[o[p-2],...o[p]];break;case 29:this.$=[o[p]];break;case 30:x.setYAxisTitle(o[p]);break;case 31:x.setYAxisTitle(o[p-1]);break;case 32:x.setYAxisTitle({type:"text",text:""});break;case 33:x.setYAxisRangeData(Number(o[p-2]),Number(o[p]));break;case 37:this.$={text:o[p],type:"text"};break;case 38:this.$={text:o[p],type:"text"};break;case 39:this.$={text:o[p],type:"markdown"};break;case 40:this.$=o[p];break;case 41:this.$=o[p-1]+""+o[p];break}},"anonymous"),table:[s(t,i,{3:1,4:2,7:4,5:e,34:a,35:c,36:d}),{1:[3]},s(t,i,{4:2,7:4,3:8,5:e,34:a,35:c,36:d}),s(t,i,{4:2,7:4,6:9,3:10,5:e,8:[1,11],34:a,35:c,36:d}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},s(m,[2,34]),s(m,[2,35]),s(m,[2,36]),{1:[2,1]},s(t,i,{4:2,7:4,3:21,5:e,34:a,35:c,36:d}),{1:[2,3]},s(m,[2,5]),s(t,[2,7],{4:22,34:a,35:c,36:d}),{11:23,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},{11:39,13:38,24:M,27:B,29:40,30:41,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},{11:45,15:44,27:U,33:46,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},{11:49,17:48,24:X,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},{11:52,17:51,24:X,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},{20:[1,53]},{22:[1,54]},s(h,[2,18]),{1:[2,2]},s(h,[2,8]),s(h,[2,9]),s(k,[2,37],{40:55,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l}),s(k,[2,38]),s(k,[2,39]),s(w,[2,40]),s(w,[2,42]),s(w,[2,43]),s(w,[2,44]),s(w,[2,45]),s(w,[2,46]),s(w,[2,47]),s(w,[2,48]),s(w,[2,49]),s(w,[2,50]),s(w,[2,51]),s(h,[2,10]),s(h,[2,22],{30:41,29:56,24:M,27:B}),s(h,[2,24]),s(h,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},s(h,[2,11]),s(h,[2,30],{33:60,27:U}),s(h,[2,32]),{31:[1,61]},s(h,[2,12]),{17:62,24:X},{25:63,27:S},s(h,[2,14]),{17:65,24:X},s(h,[2,16]),s(h,[2,17]),s(w,[2,41]),s(h,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},s(h,[2,31]),{27:[1,69]},s(h,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},s(h,[2,15]),s(h,[2,26]),s(h,[2,27]),{11:59,32:72,37:24,38:b,39:P,40:27,41:I,42:R,43:L,44:z,45:F,46:D,47:V,48:f,49:C,50:l},s(h,[2,33]),s(h,[2,19]),{25:73,27:S},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:n(function(r,u){if(u.recoverable)this.trace(r);else{var g=new Error(r);throw g.hash=u,g}},"parseError"),parse:n(function(r){var u=this,g=[0],x=[],A=[null],o=[],nt=this.table,p="",lt=0,Et=0,hi=2,It=1,li=o.slice.call(arguments,1),_=Object.create(this.lexer),Y={yy:{}};for(var dt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,dt)&&(Y.yy[dt]=this.yy[dt]);_.setInput(r,Y.yy),Y.yy.lexer=_,Y.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var pt=_.yylloc;o.push(pt);var ci=_.options&&_.options.ranges;typeof Y.yy.parseError=="function"?this.parseError=Y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ui(v){g.length=g.length-2*v,A.length=A.length-v,o.length=o.length-v}n(ui,"popStack");function Vt(){var v;return v=x.pop()||_.lex()||It,typeof v!="number"&&(v instanceof Array&&(x=v,v=x.pop()),v=u.symbols_[v]||v),v}n(Vt,"lex");for(var T,H,E,ft,q={},ct,O,Mt,ut;;){if(H=g[g.length-1],this.defaultActions[H]?E=this.defaultActions[H]:((T===null||typeof T>"u")&&(T=Vt()),E=nt[H]&&nt[H][T]),typeof E>"u"||!E.length||!E[0]){var yt="";ut=[];for(ct in nt[H])this.terminals_[ct]&&ct>hi&&ut.push("'"+this.terminals_[ct]+"'");_.showPosition?yt="Parse error on line "+(lt+1)+`:
2
+ `+_.showPosition()+`
3
+ Expecting `+ut.join(", ")+", got '"+(this.terminals_[T]||T)+"'":yt="Parse error on line "+(lt+1)+": Unexpected "+(T==It?"end of input":"'"+(this.terminals_[T]||T)+"'"),this.parseError(yt,{text:_.match,token:this.terminals_[T]||T,line:_.yylineno,loc:pt,expected:ut})}if(E[0]instanceof Array&&E.length>1)throw new Error("Parse Error: multiple actions possible at state: "+H+", token: "+T);switch(E[0]){case 1:g.push(T),A.push(_.yytext),o.push(_.yylloc),g.push(E[1]),T=null,Et=_.yyleng,p=_.yytext,lt=_.yylineno,pt=_.yylloc;break;case 2:if(O=this.productions_[E[1]][1],q.$=A[A.length-O],q._$={first_line:o[o.length-(O||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(O||1)].first_column,last_column:o[o.length-1].last_column},ci&&(q._$.range=[o[o.length-(O||1)].range[0],o[o.length-1].range[1]]),ft=this.performAction.apply(q,[p,Et,lt,Y.yy,E[1],A,o].concat(li)),typeof ft<"u")return ft;O&&(g=g.slice(0,-1*O*2),A=A.slice(0,-1*O),o=o.slice(0,-1*O)),g.push(this.productions_[E[1]][0]),A.push(q.$),o.push(q._$),Mt=nt[g[g.length-2]][g[g.length-1]],g.push(Mt);break;case 3:return!0}}return!0},"parse")},Lt=function(){var W={EOF:1,parseError:n(function(u,g){if(this.yy.parser)this.yy.parser.parseError(u,g);else throw new Error(u)},"parseError"),setInput:n(function(r,u){return this.yy=u||this.yy||{},this._input=r,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:n(function(){var r=this._input[0];this.yytext+=r,this.yyleng++,this.offset++,this.match+=r,this.matched+=r;var u=r.match(/(?:\r\n?|\n).*/g);return u?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),r},"input"),unput:n(function(r){var u=r.length,g=r.split(/(?:\r\n?|\n)/g);this._input=r+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-u),this.offset-=u;var x=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),g.length-1&&(this.yylineno-=g.length-1);var A=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:g?(g.length===x.length?this.yylloc.first_column:0)+x[x.length-g.length].length-g[0].length:this.yylloc.first_column-u},this.options.ranges&&(this.yylloc.range=[A[0],A[0]+this.yyleng-u]),this.yyleng=this.yytext.length,this},"unput"),more:n(function(){return this._more=!0,this},"more"),reject:n(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
4
+ `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:n(function(r){this.unput(this.match.slice(r))},"less"),pastInput:n(function(){var r=this.matched.substr(0,this.matched.length-this.match.length);return(r.length>20?"...":"")+r.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:n(function(){var r=this.match;return r.length<20&&(r+=this._input.substr(0,20-r.length)),(r.substr(0,20)+(r.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:n(function(){var r=this.pastInput(),u=new Array(r.length+1).join("-");return r+this.upcomingInput()+`
5
+ `+u+"^"},"showPosition"),test_match:n(function(r,u){var g,x,A;if(this.options.backtrack_lexer&&(A={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(A.yylloc.range=this.yylloc.range.slice(0))),x=r[0].match(/(?:\r\n?|\n).*/g),x&&(this.yylineno+=x.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:x?x[x.length-1].length-x[x.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+r[0].length},this.yytext+=r[0],this.match+=r[0],this.matches=r,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(r[0].length),this.matched+=r[0],g=this.performAction.call(this,this.yy,this,u,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),g)return g;if(this._backtrack){for(var o in A)this[o]=A[o];return!1}return!1},"test_match"),next:n(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var r,u,g,x;this._more||(this.yytext="",this.match="");for(var A=this._currentRules(),o=0;o<A.length;o++)if(g=this._input.match(this.rules[A[o]]),g&&(!u||g[0].length>u[0].length)){if(u=g,x=o,this.options.backtrack_lexer){if(r=this.test_match(g,A[o]),r!==!1)return r;if(this._backtrack){u=!1;continue}else return!1}else if(!this.options.flex)break}return u?(r=this.test_match(u,A[x]),r!==!1?r:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
6
+ `+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:n(function(){var u=this.next();return u||this.lex()},"lex"),begin:n(function(u){this.conditionStack.push(u)},"begin"),popState:n(function(){var u=this.conditionStack.length-1;return u>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:n(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:n(function(u){return u=this.conditionStack.length-1-Math.abs(u||0),u>=0?this.conditionStack[u]:"INITIAL"},"topState"),pushState:n(function(u){this.begin(u)},"pushState"),stateStackSize:n(function(){return this.conditionStack.length},"stateStackSize"),options:{"case-insensitive":!0},performAction:n(function(u,g,x,A){switch(x){case 0:break;case 1:break;case 2:return this.popState(),34;case 3:return this.popState(),34;case 4:return 34;case 5:break;case 6:return 10;case 7:return this.pushState("acc_title"),19;case 8:return this.popState(),"acc_title_value";case 9:return this.pushState("acc_descr"),21;case 10:return this.popState(),"acc_descr_value";case 11:this.pushState("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:return 5;case 15:return 5;case 16:return 8;case 17:return this.pushState("axis_data"),"X_AXIS";case 18:return this.pushState("axis_data"),"Y_AXIS";case 19:return this.pushState("axis_band_data"),24;case 20:return 31;case 21:return this.pushState("data"),16;case 22:return this.pushState("data"),18;case 23:return this.pushState("data_inner"),24;case 24:return 27;case 25:return this.popState(),26;case 26:this.popState();break;case 27:this.pushState("string");break;case 28:this.popState();break;case 29:return"STR";case 30:return 24;case 31:return 26;case 32:return 43;case 33:return"COLON";case 34:return 44;case 35:return 28;case 36:return 45;case 37:return 46;case 38:return 48;case 39:return 50;case 40:return 47;case 41:return 41;case 42:return 49;case 43:return 42;case 44:break;case 45:return 35;case 46:return 36}},"anonymous"),rules:[/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:(\r?\n))/i,/^(?:(\r?\n))/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:title\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:\{)/i,/^(?:[^\}]*)/i,/^(?:xychart-beta\b)/i,/^(?:xychart\b)/i,/^(?:(?:vertical|horizontal))/i,/^(?:x-axis\b)/i,/^(?:y-axis\b)/i,/^(?:\[)/i,/^(?:-->)/i,/^(?:line\b)/i,/^(?:bar\b)/i,/^(?:\[)/i,/^(?:[+-]?(?:\d+(?:\.\d+)?|\.\d+))/i,/^(?:\])/i,/^(?:(?:`\) \{ this\.pushState\(md_string\); \}\n<md_string>\(\?:\(\?!`"\)\.\)\+ \{ return MD_STR; \}\n<md_string>\(\?:`))/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:\[)/i,/^(?:\])/i,/^(?:[A-Za-z]+)/i,/^(?::)/i,/^(?:\+)/i,/^(?:,)/i,/^(?:=)/i,/^(?:\*)/i,/^(?:#)/i,/^(?:[\_])/i,/^(?:\.)/i,/^(?:&)/i,/^(?:-)/i,/^(?:[0-9]+)/i,/^(?:\s+)/i,/^(?:;)/i,/^(?:$)/i],conditions:{data_inner:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,24,25,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},data:{rules:[0,1,3,4,5,6,7,9,11,14,15,16,17,18,21,22,23,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},axis_band_data:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,25,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},axis_data:{rules:[0,1,2,4,5,6,7,9,11,14,15,16,17,18,19,20,21,22,24,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},title:{rules:[],inclusive:!1},md_string:{rules:[],inclusive:!1},string:{rules:[28,29],inclusive:!1},INITIAL:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0}}};return W}();$.lexer=Lt;function N(){this.yy={}}return n(N,"Parser"),N.prototype=$,$.Parser=N,new N}();mt.parser=mt;var _i=mt;function bt(s){return s.type==="bar"}n(bt,"isBarPlot");function St(s){return s.type==="band"}n(St,"isBandAxisData");function G(s){return s.type==="linear"}n(G,"isLinearAxisData");var j,Ht=(j=class{constructor(t){this.parentGroup=t}getMaxDimension(t,i){if(!this.parentGroup)return{width:t.reduce((c,d)=>Math.max(d.length,c),0)*i,height:i};const e={width:0,height:0},a=this.parentGroup.append("g").attr("visibility","hidden").attr("font-size",i);for(const c of t){const d=Si(a,1,c),m=d?d.width:c.length*i,b=d?d.height:i;e.width=Math.max(e.width,m),e.height=Math.max(e.height,b)}return a.remove(),e}},n(j,"TextDimensionCalculatorWithFont"),j),Ft=.7,Ot=.2,Q,Ut=(Q=class{constructor(t,i,e,a){this.axisConfig=t,this.title=i,this.textDimensionCalculator=e,this.axisThemeConfig=a,this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left",this.showTitle=!1,this.showLabel=!1,this.showTick=!1,this.showAxisLine=!1,this.outerPadding=0,this.titleTextHeight=0,this.labelTextHeight=0,this.range=[0,10],this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left"}setRange(t){this.range=t,this.axisPosition==="left"||this.axisPosition==="right"?this.boundingRect.height=t[1]-t[0]:this.boundingRect.width=t[1]-t[0],this.recalculateScale()}getRange(){return[this.range[0]+this.outerPadding,this.range[1]-this.outerPadding]}setAxisPosition(t){this.axisPosition=t,this.setRange(this.range)}getTickDistance(){const t=this.getRange();return Math.abs(t[0]-t[1])/this.getTickValues().length}getAxisOuterPadding(){return this.outerPadding}getLabelDimension(){return this.textDimensionCalculator.getMaxDimension(this.getTickValues().map(t=>t.toString()),this.axisConfig.labelFontSize)}recalculateOuterPaddingToDrawBar(){Ft*this.getTickDistance()>this.outerPadding*2&&(this.outerPadding=Math.floor(Ft*this.getTickDistance()/2)),this.recalculateScale()}calculateSpaceIfDrawnHorizontally(t){let i=t.height;if(this.axisConfig.showAxisLine&&i>this.axisConfig.axisLineWidth&&(i-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const e=this.getLabelDimension(),a=Ot*t.width;this.outerPadding=Math.min(e.width/2,a);const c=e.height+this.axisConfig.labelPadding*2;this.labelTextHeight=e.height,c<=i&&(i-=c,this.showLabel=!0)}if(this.axisConfig.showTick&&i>=this.axisConfig.tickLength&&(this.showTick=!0,i-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const e=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),a=e.height+this.axisConfig.titlePadding*2;this.titleTextHeight=e.height,a<=i&&(i-=a,this.showTitle=!0)}this.boundingRect.width=t.width,this.boundingRect.height=t.height-i}calculateSpaceIfDrawnVertical(t){let i=t.width;if(this.axisConfig.showAxisLine&&i>this.axisConfig.axisLineWidth&&(i-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const e=this.getLabelDimension(),a=Ot*t.height;this.outerPadding=Math.min(e.height/2,a);const c=e.width+this.axisConfig.labelPadding*2;c<=i&&(i-=c,this.showLabel=!0)}if(this.axisConfig.showTick&&i>=this.axisConfig.tickLength&&(this.showTick=!0,i-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const e=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),a=e.height+this.axisConfig.titlePadding*2;this.titleTextHeight=e.height,a<=i&&(i-=a,this.showTitle=!0)}this.boundingRect.width=t.width-i,this.boundingRect.height=t.height}calculateSpace(t){return this.axisPosition==="left"||this.axisPosition==="right"?this.calculateSpaceIfDrawnVertical(t):this.calculateSpaceIfDrawnHorizontally(t),this.recalculateScale(),{width:this.boundingRect.width,height:this.boundingRect.height}}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}getDrawableElementsForLeftAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.x+this.boundingRect.width-this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["left-axis","axisl-line"],data:[{path:`M ${i},${this.boundingRect.y} L ${i},${this.boundingRect.y+this.boundingRect.height} `,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["left-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.boundingRect.x+this.boundingRect.width-(this.showLabel?this.axisConfig.labelPadding:0)-(this.showTick?this.axisConfig.tickLength:0)-(this.showAxisLine?this.axisConfig.axisLineWidth:0),y:this.getScaleValue(i),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"middle",horizontalPos:"right"}))}),this.showTick){const i=this.boundingRect.x+this.boundingRect.width-(this.showAxisLine?this.axisConfig.axisLineWidth:0);t.push({type:"path",groupTexts:["left-axis","ticks"],data:this.getTickValues().map(e=>({path:`M ${i},${this.getScaleValue(e)} L ${i-this.axisConfig.tickLength},${this.getScaleValue(e)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["left-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.axisConfig.titlePadding,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:270,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElementsForBottomAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.y+this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["bottom-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${i} L ${this.boundingRect.x+this.boundingRect.width},${i}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["bottom-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.getScaleValue(i),y:this.boundingRect.y+this.axisConfig.labelPadding+(this.showTick?this.axisConfig.tickLength:0)+(this.showAxisLine?this.axisConfig.axisLineWidth:0),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const i=this.boundingRect.y+(this.showAxisLine?this.axisConfig.axisLineWidth:0);t.push({type:"path",groupTexts:["bottom-axis","ticks"],data:this.getTickValues().map(e=>({path:`M ${this.getScaleValue(e)},${i} L ${this.getScaleValue(e)},${i+this.axisConfig.tickLength}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["bottom-axis","title"],data:[{text:this.title,x:this.range[0]+(this.range[1]-this.range[0])/2,y:this.boundingRect.y+this.boundingRect.height-this.axisConfig.titlePadding-this.titleTextHeight,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElementsForTopAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.y+this.boundingRect.height-this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["top-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${i} L ${this.boundingRect.x+this.boundingRect.width},${i}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["top-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.getScaleValue(i),y:this.boundingRect.y+(this.showTitle?this.titleTextHeight+this.axisConfig.titlePadding*2:0)+this.axisConfig.labelPadding,fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const i=this.boundingRect.y;t.push({type:"path",groupTexts:["top-axis","ticks"],data:this.getTickValues().map(e=>({path:`M ${this.getScaleValue(e)},${i+this.boundingRect.height-(this.showAxisLine?this.axisConfig.axisLineWidth:0)} L ${this.getScaleValue(e)},${i+this.boundingRect.height-this.axisConfig.tickLength-(this.showAxisLine?this.axisConfig.axisLineWidth:0)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["top-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.axisConfig.titlePadding,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElements(){if(this.axisPosition==="left")return this.getDrawableElementsForLeftAxis();if(this.axisPosition==="right")throw Error("Drawing of right axis is not implemented");return this.axisPosition==="bottom"?this.getDrawableElementsForBottomAxis():this.axisPosition==="top"?this.getDrawableElementsForTopAxis():[]}},n(Q,"BaseAxis"),Q),K,ki=(K=class extends Ut{constructor(t,i,e,a,c){super(t,a,c,i),this.categories=e,this.scale=Bt().domain(this.categories).range(this.getRange())}setRange(t){super.setRange(t)}recalculateScale(){this.scale=Bt().domain(this.categories).range(this.getRange()).paddingInner(1).paddingOuter(0).align(.5),Nt.trace("BandAxis axis final categories, range: ",this.categories,this.getRange())}getTickValues(){return this.categories}getScaleValue(t){return this.scale(t)??this.getRange()[0]}},n(K,"BandAxis"),K),Z,Ti=(Z=class extends Ut{constructor(t,i,e,a,c){super(t,a,c,i),this.domain=e,this.scale=Wt().domain(this.domain).range(this.getRange())}getTickValues(){return this.scale.ticks()}recalculateScale(){const t=[...this.domain];this.axisPosition==="left"&&t.reverse(),this.scale=Wt().domain(t).range(this.getRange())}getScaleValue(t){return this.scale(t)}},n(Z,"LinearAxis"),Z);function At(s,t,i,e){const a=new Ht(e);return St(s)?new ki(t,i,s.categories,s.title,a):new Ti(t,i,[s.min,s.max],s.title,a)}n(At,"getAxis");var J,Ri=(J=class{constructor(t,i,e,a){this.textDimensionCalculator=t,this.chartConfig=i,this.chartData=e,this.chartThemeConfig=a,this.boundingRect={x:0,y:0,width:0,height:0},this.showChartTitle=!1}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateSpace(t){const i=this.textDimensionCalculator.getMaxDimension([this.chartData.title],this.chartConfig.titleFontSize),e=Math.max(i.width,t.width),a=i.height+2*this.chartConfig.titlePadding;return i.width<=e&&i.height<=a&&this.chartConfig.showTitle&&this.chartData.title&&(this.boundingRect.width=e,this.boundingRect.height=a,this.showChartTitle=!0),{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){const t=[];return this.showChartTitle&&t.push({groupTexts:["chart-title"],type:"text",data:[{fontSize:this.chartConfig.titleFontSize,text:this.chartData.title,verticalPos:"middle",horizontalPos:"center",x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.chartThemeConfig.titleColor,rotation:0}]}),t}},n(J,"ChartTitle"),J);function $t(s,t,i,e){const a=new Ht(e);return new Ri(a,s,t,i)}n($t,"getChartTitleComponent");var tt,Di=(tt=class{constructor(t,i,e,a,c){this.plotData=t,this.xAxis=i,this.yAxis=e,this.orientation=a,this.plotIndex=c}getDrawableElement(){const t=this.plotData.data.map(e=>[this.xAxis.getScaleValue(e[0]),this.yAxis.getScaleValue(e[1])]);let i;return this.orientation==="horizontal"?i=zt().y(e=>e[0]).x(e=>e[1])(t):i=zt().x(e=>e[0]).y(e=>e[1])(t),i?[{groupTexts:["plot",`line-plot-${this.plotIndex}`],type:"path",data:[{path:i,strokeFill:this.plotData.strokeFill,strokeWidth:this.plotData.strokeWidth}]}]:[]}},n(tt,"LinePlot"),tt),it,vi=(it=class{constructor(t,i,e,a,c,d){this.barData=t,this.boundingRect=i,this.xAxis=e,this.yAxis=a,this.orientation=c,this.plotIndex=d}getDrawableElement(){const t=this.barData.data.map(c=>[this.xAxis.getScaleValue(c[0]),this.yAxis.getScaleValue(c[1])]),e=Math.min(this.xAxis.getAxisOuterPadding()*2,this.xAxis.getTickDistance())*(1-.05),a=e/2;return this.orientation==="horizontal"?[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:t.map(c=>({x:this.boundingRect.x,y:c[0]-a,height:e,width:c[1]-this.boundingRect.x,fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]:[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:t.map(c=>({x:c[0]-a,y:c[1],width:e,height:this.boundingRect.y+this.boundingRect.height-c[1],fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]}},n(it,"BarPlot"),it),et,Pi=(et=class{constructor(t,i,e){this.chartConfig=t,this.chartData=i,this.chartThemeConfig=e,this.boundingRect={x:0,y:0,width:0,height:0}}setAxes(t,i){this.xAxis=t,this.yAxis=i}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateSpace(t){return this.boundingRect.width=t.width,this.boundingRect.height=t.height,{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){if(!(this.xAxis&&this.yAxis))throw Error("Axes must be passed to render Plots");const t=[];for(const[i,e]of this.chartData.plots.entries())switch(e.type){case"line":{const a=new Di(e,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,i);t.push(...a.getDrawableElement())}break;case"bar":{const a=new vi(e,this.boundingRect,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,i);t.push(...a.getDrawableElement())}break}return t}},n(et,"BasePlot"),et);function qt(s,t,i){return new Pi(s,t,i)}n(qt,"getPlotComponent");var st,Li=(st=class{constructor(t,i,e,a){this.chartConfig=t,this.chartData=i,this.componentStore={title:$t(t,i,e,a),plot:qt(t,i,e),xAxis:At(i.xAxis,t.xAxis,{titleColor:e.xAxisTitleColor,labelColor:e.xAxisLabelColor,tickColor:e.xAxisTickColor,axisLineColor:e.xAxisLineColor},a),yAxis:At(i.yAxis,t.yAxis,{titleColor:e.yAxisTitleColor,labelColor:e.yAxisLabelColor,tickColor:e.yAxisTickColor,axisLineColor:e.yAxisLineColor},a)}}calculateVerticalSpace(){let t=this.chartConfig.width,i=this.chartConfig.height,e=0,a=0,c=Math.floor(t*this.chartConfig.plotReservedSpacePercent/100),d=Math.floor(i*this.chartConfig.plotReservedSpacePercent/100),m=this.componentStore.plot.calculateSpace({width:c,height:d});t-=m.width,i-=m.height,m=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:i}),a=m.height,i-=m.height,this.componentStore.xAxis.setAxisPosition("bottom"),m=this.componentStore.xAxis.calculateSpace({width:t,height:i}),i-=m.height,this.componentStore.yAxis.setAxisPosition("left"),m=this.componentStore.yAxis.calculateSpace({width:t,height:i}),e=m.width,t-=m.width,t>0&&(c+=t,t=0),i>0&&(d+=i,i=0),this.componentStore.plot.calculateSpace({width:c,height:d}),this.componentStore.plot.setBoundingBoxXY({x:e,y:a}),this.componentStore.xAxis.setRange([e,e+c]),this.componentStore.xAxis.setBoundingBoxXY({x:e,y:a+d}),this.componentStore.yAxis.setRange([a,a+d]),this.componentStore.yAxis.setBoundingBoxXY({x:0,y:a}),this.chartData.plots.some(b=>bt(b))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateHorizontalSpace(){let t=this.chartConfig.width,i=this.chartConfig.height,e=0,a=0,c=0,d=Math.floor(t*this.chartConfig.plotReservedSpacePercent/100),m=Math.floor(i*this.chartConfig.plotReservedSpacePercent/100),b=this.componentStore.plot.calculateSpace({width:d,height:m});t-=b.width,i-=b.height,b=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:i}),e=b.height,i-=b.height,this.componentStore.xAxis.setAxisPosition("left"),b=this.componentStore.xAxis.calculateSpace({width:t,height:i}),t-=b.width,a=b.width,this.componentStore.yAxis.setAxisPosition("top"),b=this.componentStore.yAxis.calculateSpace({width:t,height:i}),i-=b.height,c=e+b.height,t>0&&(d+=t,t=0),i>0&&(m+=i,i=0),this.componentStore.plot.calculateSpace({width:d,height:m}),this.componentStore.plot.setBoundingBoxXY({x:a,y:c}),this.componentStore.yAxis.setRange([a,a+d]),this.componentStore.yAxis.setBoundingBoxXY({x:a,y:e}),this.componentStore.xAxis.setRange([c,c+m]),this.componentStore.xAxis.setBoundingBoxXY({x:0,y:c}),this.chartData.plots.some(P=>bt(P))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateSpace(){this.chartConfig.chartOrientation==="horizontal"?this.calculateHorizontalSpace():this.calculateVerticalSpace()}getDrawableElement(){this.calculateSpace();const t=[];this.componentStore.plot.setAxes(this.componentStore.xAxis,this.componentStore.yAxis);for(const i of Object.values(this.componentStore))t.push(...i.getDrawableElements());return t}},n(st,"Orchestrator"),st),at,Ei=(at=class{static build(t,i,e,a){return new Li(t,i,e,a).getDrawableElement()}},n(at,"XYChartBuilder"),at),ot=0,Gt,rt=Tt(),ht=kt(),y=Rt(),wt=ht.plotColorPalette.split(",").map(s=>s.trim()),gt=!1,_t=!1;function kt(){const s=Ci(),t=Ct();return Yt(s.xyChart,t.themeVariables.xyChart)}n(kt,"getChartDefaultThemeConfig");function Tt(){const s=Ct();return Yt(wi.xyChart,s.xyChart)}n(Tt,"getChartDefaultConfig");function Rt(){return{yAxis:{type:"linear",title:"",min:1/0,max:-1/0},xAxis:{type:"band",title:"",categories:[]},title:"",plots:[]}}n(Rt,"getChartDefaultData");function xt(s){const t=Ct();return Ai(s.trim(),t)}n(xt,"textSanitizer");function jt(s){Gt=s}n(jt,"setTmpSVGG");function Qt(s){s==="horizontal"?rt.chartOrientation="horizontal":rt.chartOrientation="vertical"}n(Qt,"setOrientation");function Kt(s){y.xAxis.title=xt(s.text)}n(Kt,"setXAxisTitle");function Dt(s,t){y.xAxis={type:"linear",title:y.xAxis.title,min:s,max:t},gt=!0}n(Dt,"setXAxisRangeData");function Zt(s){y.xAxis={type:"band",title:y.xAxis.title,categories:s.map(t=>xt(t.text))},gt=!0}n(Zt,"setXAxisBand");function Jt(s){y.yAxis.title=xt(s.text)}n(Jt,"setYAxisTitle");function ti(s,t){y.yAxis={type:"linear",title:y.yAxis.title,min:s,max:t},_t=!0}n(ti,"setYAxisRangeData");function ii(s){const t=Math.min(...s),i=Math.max(...s),e=G(y.yAxis)?y.yAxis.min:1/0,a=G(y.yAxis)?y.yAxis.max:-1/0;y.yAxis={type:"linear",title:y.yAxis.title,min:Math.min(e,t),max:Math.max(a,i)}}n(ii,"setYAxisRangeFromPlotData");function vt(s){let t=[];if(s.length===0)return t;if(!gt){const i=G(y.xAxis)?y.xAxis.min:1/0,e=G(y.xAxis)?y.xAxis.max:-1/0;Dt(Math.min(i,1),Math.max(e,s.length))}if(_t||ii(s),St(y.xAxis)&&(t=y.xAxis.categories.map((i,e)=>[i,s[e]])),G(y.xAxis)){const i=y.xAxis.min,e=y.xAxis.max,a=(e-i)/(s.length-1),c=[];for(let d=i;d<=e;d+=a)c.push(`${d}`);t=c.map((d,m)=>[d,s[m]])}return t}n(vt,"transformDataWithoutCategory");function Pt(s){return wt[s===0?0:s%wt.length]}n(Pt,"getPlotColorFromPalette");function ei(s,t){const i=vt(t);y.plots.push({type:"line",strokeFill:Pt(ot),strokeWidth:2,data:i}),ot++}n(ei,"setLineData");function si(s,t){const i=vt(t);y.plots.push({type:"bar",fill:Pt(ot),data:i}),ot++}n(si,"setBarData");function ai(){if(y.plots.length===0)throw Error("No Plot to render, please provide a plot with some data");return y.title=Xt(),Ei.build(rt,y,ht,Gt)}n(ai,"getDrawableElem");function ni(){return ht}n(ni,"getChartThemeConfig");function oi(){return rt}n(oi,"getChartConfig");function ri(){return y}n(ri,"getXYChartData");var Ii=n(function(){bi(),ot=0,rt=Tt(),y=Rt(),ht=kt(),wt=ht.plotColorPalette.split(",").map(s=>s.trim()),gt=!1,_t=!1},"clear"),Vi={getDrawableElem:ai,clear:Ii,setAccTitle:fi,getAccTitle:pi,setDiagramTitle:di,getDiagramTitle:Xt,getAccDescription:xi,setAccDescription:gi,setOrientation:Qt,setXAxisTitle:Kt,setXAxisRangeData:Dt,setXAxisBand:Zt,setYAxisTitle:Jt,setYAxisRangeData:ti,setLineData:ei,setBarData:si,setTmpSVGG:jt,getChartThemeConfig:ni,getChartConfig:oi,getXYChartData:ri},Mi=n((s,t,i,e)=>{const a=e.db,c=a.getChartThemeConfig(),d=a.getChartConfig(),m=a.getXYChartData().plots[0].data.map(f=>f[1]);function b(f){return f==="top"?"text-before-edge":"middle"}n(b,"getDominantBaseLine");function P(f){return f==="left"?"start":f==="right"?"end":"middle"}n(P,"getTextAnchor");function I(f){return`translate(${f.x}, ${f.y}) rotate(${f.rotation||0})`}n(I,"getTextTransformation"),Nt.debug(`Rendering xychart chart
7
+ `+s);const R=yi(t),L=R.append("g").attr("class","main"),z=L.append("rect").attr("width",d.width).attr("height",d.height).attr("class","background");mi(R,d.height,d.width,!0),R.attr("viewBox",`0 0 ${d.width} ${d.height}`),z.attr("fill",c.backgroundColor),a.setTmpSVGG(R.append("g").attr("class","mermaid-tmp-group"));const F=a.getDrawableElem(),D={};function V(f){let C=L,l="";for(const[M]of f.entries()){let B=L;M>0&&D[l]&&(B=D[l]),l+=f[M],C=D[l],C||(C=D[l]=B.append("g").attr("class",f[M]))}return C}n(V,"getGroup");for(const f of F){if(f.data.length===0)continue;const C=V(f.groupTexts);switch(f.type){case"rect":if(C.selectAll("rect").data(f.data).enter().append("rect").attr("x",l=>l.x).attr("y",l=>l.y).attr("width",l=>l.width).attr("height",l=>l.height).attr("fill",l=>l.fill).attr("stroke",l=>l.strokeFill).attr("stroke-width",l=>l.strokeWidth),d.showDataLabel)if(d.chartOrientation==="horizontal"){let l=function(h,k){const{data:w,label:S}=h;return k*S.length*M<=w.width-10};n(l,"fitsHorizontally");const M=.7,B=f.data.map((h,k)=>({data:h,label:m[k].toString()})).filter(h=>h.data.width>0&&h.data.height>0),U=B.map(h=>{const{data:k}=h;let w=k.height*.7;for(;!l(h,w)&&w>0;)w-=1;return w}),X=Math.floor(Math.min(...U));C.selectAll("text").data(B).enter().append("text").attr("x",h=>h.data.x+h.data.width-10).attr("y",h=>h.data.y+h.data.height/2).attr("text-anchor","end").attr("dominant-baseline","middle").attr("fill","black").attr("font-size",`${X}px`).text(h=>h.label)}else{let l=function(h,k,w){const{data:S,label:$}=h,N=k*$.length*.7,W=S.x+S.width/2,r=W-N/2,u=W+N/2,g=r>=S.x&&u<=S.x+S.width,x=S.y+w+k<=S.y+S.height;return g&&x};n(l,"fitsInBar");const M=10,B=f.data.map((h,k)=>({data:h,label:m[k].toString()})).filter(h=>h.data.width>0&&h.data.height>0),U=B.map(h=>{const{data:k,label:w}=h;let S=k.width/(w.length*.7);for(;!l(h,S,M)&&S>0;)S-=1;return S}),X=Math.floor(Math.min(...U));C.selectAll("text").data(B).enter().append("text").attr("x",h=>h.data.x+h.data.width/2).attr("y",h=>h.data.y+M).attr("text-anchor","middle").attr("dominant-baseline","hanging").attr("fill","black").attr("font-size",`${X}px`).text(h=>h.label)}break;case"text":C.selectAll("text").data(f.data).enter().append("text").attr("x",0).attr("y",0).attr("fill",l=>l.fill).attr("font-size",l=>l.fontSize).attr("dominant-baseline",l=>b(l.verticalPos)).attr("text-anchor",l=>P(l.horizontalPos)).attr("transform",l=>I(l)).text(l=>l.text);break;case"path":C.selectAll("path").data(f.data).enter().append("path").attr("d",l=>l.path).attr("fill",l=>l.fill?l.fill:"none").attr("stroke",l=>l.strokeFill).attr("stroke-width",l=>l.strokeWidth);break}}},"draw"),Bi={draw:Mi},zi={parser:_i,db:Vi,renderer:Bi};export{zi as diagram};
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>API Coverage Analyzer Dashboard</title>
8
- <script type="module" crossorigin src="/assets/index-B2mS1bcV.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DBTGeaha.css">
8
+ <script type="module" crossorigin src="/assets/index-k7QMCdxo.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-HrRX8fCW.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/dist/src/index.js CHANGED
@@ -55,14 +55,19 @@ const index_3 = require("./intelligence/index");
55
55
  const observability_2 = require("./observability");
56
56
  const buildSummary_1 = require("./summary/buildSummary");
57
57
  const prSummary_1 = require("./summary/prSummary");
58
+ const summaryTypes_1 = require("./summary/summaryTypes");
58
59
  const astAnalysisOrchestrator_1 = require("./ast/astAnalysisOrchestrator");
59
60
  const projectDiscovery_1 = require("./discovery/projectDiscovery");
60
61
  const businessRuleInference_1 = require("./inference/businessRuleInference");
61
62
  const integrationFlowInference_1 = require("./inference/integrationFlowInference");
63
+ const routeInference_1 = require("./inference/routeInference");
64
+ const scanManifest_1 = require("./inference/scanManifest");
62
65
  const serveDashboard_1 = require("./serveDashboard");
63
66
  // Register all language AST analyzers at startup.
64
67
  // This side-effect import ensures each language module's registerAnalyzer() call runs.
65
68
  (0, astAnalysisOrchestrator_1.registerAllAnalyzers)();
69
+ /** Keywords that indicate a test is exercising an error/failure path. */
70
+ const ERROR_TEST_KEYWORDS = ['error', 'fail', 'throw', 'exception', 'reject', 'invalid', 'blank', 'missing'];
66
71
  const program = new commander_1.Command();
67
72
  program
68
73
  .name('api-tests-coverage-analyzer')
@@ -1499,7 +1504,161 @@ program
1499
1504
  }
1500
1505
  }
1501
1506
  else {
1502
- warnings.push('No API spec files found; endpoint/parameter/error coverage analysis skipped.');
1507
+ warnings.push('No API spec files found; attempting route inference for endpoint/error coverage.');
1508
+ // ── 4a-alt. Inferred route endpoint coverage ──────────────────────────
1509
+ try {
1510
+ const routeResult = (0, routeInference_1.inferRoutes)(artifacts.serviceFiles);
1511
+ if (routeResult.routes.length > 0) {
1512
+ const routesPath = (0, routeInference_1.writeInferredRoutes)(routeResult, reportsDir);
1513
+ console.log(`\nRoute Inference`);
1514
+ console.log(` Routes detected in service code: ${routeResult.routes.length}`);
1515
+ console.log(` Written to: ${routesPath}`);
1516
+ console.log(`\nAnalyzing endpoint coverage (from inferred routes)...`);
1517
+ // Read test file contents for matching
1518
+ const testContents = artifacts.testFiles.map((tf) => {
1519
+ try {
1520
+ return { file: tf, content: fsMod.readFileSync(tf, 'utf-8') };
1521
+ }
1522
+ catch {
1523
+ return { file: tf, content: '' };
1524
+ }
1525
+ });
1526
+ // Extract test descriptions for fine-grained matching
1527
+ const TEST_DECL_PATTERN = /\b(?:test|it)\s*\(\s*(['"`])([\s\S]*?)\1/g;
1528
+ const testEntries = testContents.map(({ file, content }) => {
1529
+ const descriptions = [];
1530
+ const contentLower = content.toLowerCase();
1531
+ let m;
1532
+ TEST_DECL_PATTERN.lastIndex = 0;
1533
+ while ((m = TEST_DECL_PATTERN.exec(content)) !== null) {
1534
+ descriptions.push(m[2].toLowerCase());
1535
+ }
1536
+ return { file, contentLower, descriptions };
1537
+ });
1538
+ const endpointItems = routeResult.routes.map((route) => {
1539
+ var _a;
1540
+ const pathSegments = route.path.split('/').filter((s) => s.length > 1 && !s.startsWith(':'));
1541
+ const method = route.method.toLowerCase();
1542
+ // Leaf path segment is the most specific identifier (e.g., "comments", "favorite", "feed")
1543
+ const leafSegment = (_a = pathSegments[pathSegments.length - 1]) !== null && _a !== void 0 ? _a : '';
1544
+ const matchedTests = [];
1545
+ for (const { file, contentLower, descriptions } of testEntries) {
1546
+ let matched = false;
1547
+ // Priority 1: handler function name appears in test file imports/calls
1548
+ if (route.handlerFunction) {
1549
+ const fnLower = route.handlerFunction.toLowerCase();
1550
+ if (contentLower.includes(fnLower)) {
1551
+ matched = true;
1552
+ }
1553
+ }
1554
+ // Priority 2: test description mentions method + leaf path segment
1555
+ if (!matched && leafSegment.length > 2) {
1556
+ matched = descriptions.some((desc) => desc.includes(method) && desc.includes(leafSegment));
1557
+ }
1558
+ // Priority 3: test description mentions the exact path
1559
+ if (!matched && route.path.length >= 1) {
1560
+ matched = descriptions.some((desc) => desc.includes(route.path.toLowerCase()));
1561
+ }
1562
+ // Priority 4: test file directly calls the URL path (e.g., axios.get('/articles'))
1563
+ if (!matched && pathSegments.length > 0) {
1564
+ // Check for full path string in file (e.g., axios.get('/articles/feed'))
1565
+ const quotedPathPattern = new RegExp(`['"\`]${route.path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"\`]`);
1566
+ if (quotedPathPattern.test(contentLower)) {
1567
+ matched = true;
1568
+ }
1569
+ }
1570
+ if (matched) {
1571
+ matchedTests.push(path.basename(file));
1572
+ }
1573
+ }
1574
+ const covered = matchedTests.length > 0;
1575
+ return {
1576
+ id: `${route.method.toUpperCase()} ${route.path}`,
1577
+ covered,
1578
+ matchedTests,
1579
+ handler_function: route.handlerFunction,
1580
+ source_file: route.sourceFile,
1581
+ line_number: route.lineNumber,
1582
+ };
1583
+ });
1584
+ const coveredCount = endpointItems.filter((i) => i.covered).length;
1585
+ const pct = endpointItems.length > 0 ? Math.round((coveredCount / endpointItems.length) * 100) : 0;
1586
+ const endpointResult = {
1587
+ type: 'endpoint',
1588
+ totalItems: endpointItems.length,
1589
+ coveredItems: coveredCount,
1590
+ coveragePercent: pct,
1591
+ details: {
1592
+ total: endpointItems.length,
1593
+ covered: coveredCount,
1594
+ percentage: pct,
1595
+ items: endpointItems,
1596
+ source: 'inferred',
1597
+ },
1598
+ };
1599
+ allCoverageResults.push(endpointResult);
1600
+ console.log(` ${coveredCount}/${endpointItems.length} inferred routes have test coverage (${pct}%)`);
1601
+ // ── 4c-alt. Error coverage from inferred routes + rules ──────────
1602
+ if (inferredRulesResult && inferredRulesResult.rules.length > 0) {
1603
+ console.log(`\nAnalyzing error coverage (from inferred business rules)...`);
1604
+ const errorCandidateRules = inferredRulesResult.rules.filter((r) => r.type === 'validation' || r.type === 'business_logic');
1605
+ const errorItems = errorCandidateRules.map((rule) => {
1606
+ var _a;
1607
+ const matchedTestDescriptions = [];
1608
+ for (const { file, descriptions } of testEntries) {
1609
+ // Match at TEST DESCRIPTION level, not file level
1610
+ // Require: description contains an error indicator + at least one specific keyword
1611
+ const specificKws = (_a = rule.specificKeywords) !== null && _a !== void 0 ? _a : [];
1612
+ const matchingDescs = descriptions.filter((desc) => {
1613
+ const hasErrorKeyword = ERROR_TEST_KEYWORDS.some((kw) => desc.includes(kw));
1614
+ if (!hasErrorKeyword)
1615
+ return false;
1616
+ // If we have specific keywords, at least one must match in the description
1617
+ if (specificKws.length > 0) {
1618
+ return specificKws.some((kw) => desc.includes(kw.toLowerCase()));
1619
+ }
1620
+ // No specific keywords — use handler function name as fallback
1621
+ return true;
1622
+ });
1623
+ if (matchingDescs.length > 0) {
1624
+ matchedTestDescriptions.push(...matchingDescs.map((d) => `[${path.basename(file)}] ${d}`));
1625
+ }
1626
+ }
1627
+ return {
1628
+ id: rule.id,
1629
+ description: rule.condition,
1630
+ covered: matchedTestDescriptions.length > 0,
1631
+ matchedTests: matchedTestDescriptions,
1632
+ source_location: rule.source_location,
1633
+ code_snippet: rule.code_snippet,
1634
+ };
1635
+ });
1636
+ const errorCovered = errorItems.filter((i) => i.covered).length;
1637
+ const errorPct = errorItems.length > 0 ? Math.round((errorCovered / errorItems.length) * 100) : 0;
1638
+ const errorResult = {
1639
+ type: 'error',
1640
+ totalItems: errorItems.length,
1641
+ coveredItems: errorCovered,
1642
+ coveragePercent: errorPct,
1643
+ details: {
1644
+ total: errorItems.length,
1645
+ covered: errorCovered,
1646
+ percentage: errorPct,
1647
+ items: errorItems,
1648
+ source: 'inferred',
1649
+ },
1650
+ };
1651
+ allCoverageResults.push(errorResult);
1652
+ console.log(` ${errorCovered}/${errorItems.length} inferred error scenarios have test coverage (${errorPct}%)`);
1653
+ }
1654
+ }
1655
+ else {
1656
+ warnings.push('No routes detected in service files; endpoint coverage skipped.');
1657
+ }
1658
+ }
1659
+ catch (err) {
1660
+ warnings.push(`Route/error inference failed: ${err instanceof Error ? err.message : String(err)}`);
1661
+ }
1503
1662
  }
1504
1663
  // ── 4d. Business rules coverage ─────────────────────────────────────────
1505
1664
  const businessRulesYaml = path.join(rootDir, 'business-rules.yaml');
@@ -1525,22 +1684,27 @@ program
1525
1684
  }
1526
1685
  }
1527
1686
  else if (inferredRulesResult && inferredRulesResult.rules.length > 0) {
1528
- // Auto-inferred: derive keywords from rule name, condition, and endpoint
1687
+ // Auto-inferred: use specificKeywords from rule for accurate test matching
1529
1688
  try {
1530
1689
  console.log(`\nAnalyzing business rules coverage (from inferred rules)...`);
1531
1690
  const syntheticRules = inferredRulesResult.rules.map((r) => {
1532
- var _a;
1533
1691
  const kwSet = new Set();
1534
- // Words from the rule name (e.g. "amount-exceeds-balance" → ["amount", "exceeds", "balance"])
1535
- r.name.toLowerCase().split(/[-_\s]+/).forEach((w) => { if (w.length > 2)
1536
- kwSet.add(w); });
1537
- // Identifiers from the condition expression
1538
- ((_a = r.condition.match(/\b[a-zA-Z][a-zA-Z0-9]{3,}\b/g)) !== null && _a !== void 0 ? _a : [])
1539
- .forEach((w) => kwSet.add(w.toLowerCase()));
1692
+ // Use specificKeywords extracted from the condition (most accurate)
1693
+ if (r.specificKeywords && r.specificKeywords.length > 0) {
1694
+ r.specificKeywords.forEach((kw) => { if (!businessRuleInference_1.KEYWORD_STOP_WORDS.has(kw))
1695
+ kwSet.add(kw); });
1696
+ }
1697
+ else {
1698
+ // Fallback: words from rule name only (filter stop words)
1699
+ r.name.toLowerCase().split(/[-_\s]+/).forEach((w) => {
1700
+ if (w.length > 2 && !businessRuleInference_1.KEYWORD_STOP_WORDS.has(w))
1701
+ kwSet.add(w);
1702
+ });
1703
+ }
1540
1704
  // Non-trivial path segments from endpoint
1541
1705
  if (r.endpoint) {
1542
1706
  r.endpoint.toLowerCase().split(/[/.\s:]+/)
1543
- .forEach((w) => { if (w.length > 2 && !/^(api|v\d)$/.test(w))
1707
+ .forEach((w) => { if (w.length > 2 && !/^(api|v\d)$/.test(w) && !businessRuleInference_1.KEYWORD_STOP_WORDS.has(w))
1544
1708
  kwSet.add(w); });
1545
1709
  }
1546
1710
  return {
@@ -1558,7 +1722,19 @@ program
1558
1722
  totalItems: bizReport.total,
1559
1723
  coveredItems: bizReport.covered,
1560
1724
  coveragePercent: bizReport.percentage,
1561
- details: bizReport,
1725
+ details: {
1726
+ ...bizReport,
1727
+ inferred_details: inferredRulesResult.rules.reduce((acc, r) => {
1728
+ acc[r.id] = {
1729
+ source_location: r.source_location,
1730
+ condition: r.condition,
1731
+ code_snippet: r.code_snippet,
1732
+ type: r.type,
1733
+ specificKeywords: r.specificKeywords,
1734
+ };
1735
+ return acc;
1736
+ }, {}),
1737
+ },
1562
1738
  };
1563
1739
  allCoverageResults.push(bizResult);
1564
1740
  console.log(` ${bizReport.covered}/${bizReport.total} inferred business rules have test coverage (${bizReport.percentage}%)`);
@@ -1621,8 +1797,69 @@ program
1621
1797
  if (allCoverageResults.length > 0) {
1622
1798
  const observabilityInfo = (0, observability_1.buildObservabilityInfo)(metricsPort);
1623
1799
  (0, reporting_1.generateMultiFormatReports)(allCoverageResults, ['json'], reportsDir, {}, observabilityInfo);
1800
+ // Append discoveryInfo to coverage-summary.json for the dashboard
1801
+ const summaryPath = path.join(reportsDir, 'coverage-summary.json');
1802
+ try {
1803
+ const summaryJson = JSON.parse(fsMod.readFileSync(summaryPath, 'utf-8'));
1804
+ summaryJson.discoveryInfo = {
1805
+ projectRoot: rootDir,
1806
+ analyzedAt: new Date().toISOString(),
1807
+ languages: artifacts.languages,
1808
+ frameworks: artifacts.frameworks,
1809
+ serviceFilesCount: artifacts.serviceFiles.length,
1810
+ testFilesCount: artifacts.testFiles.length,
1811
+ specFilesCount: artifacts.specs.length,
1812
+ analysisMode: artifacts.specs.length > 0 ? 'explicit-spec' : 'inferred',
1813
+ };
1814
+ fsMod.writeFileSync(summaryPath, JSON.stringify(summaryJson, null, 2), 'utf-8');
1815
+ }
1816
+ catch {
1817
+ // Non-fatal — discovery info is also in scan-manifest.json
1818
+ }
1624
1819
  console.log(`\nReports written to: ${reportsDir}`);
1625
1820
  }
1821
+ // ── 4f. Write scan manifest ────────────────────────────────────────────
1822
+ try {
1823
+ const scanTypes = allCoverageResults.map((r) => ({
1824
+ type: r.type,
1825
+ source: artifacts.specs.length > 0 ? 'explicit' : 'inferred',
1826
+ itemsFound: r.totalItems,
1827
+ itemsCovered: r.coveredItems,
1828
+ coveragePercent: r.coveragePercent,
1829
+ }));
1830
+ // Add skipped types (exclude 'business' and 'integration' since these are always attempted
1831
+ // via rule/flow inference regardless of whether a spec file is present; their absence from
1832
+ // allCoverageResults means no rules or flows were discovered, which is informative on its own.)
1833
+ const coveredTypes = new Set(allCoverageResults.map((r) => r.type));
1834
+ for (const skippedType of summaryTypes_1.KNOWN_METRIC_TYPES.filter((t) => t !== 'business' && t !== 'integration')) {
1835
+ if (!coveredTypes.has(skippedType)) {
1836
+ scanTypes.push({
1837
+ type: skippedType,
1838
+ source: 'skipped',
1839
+ reason: artifacts.specs.length === 0 ? 'No API spec and no routes detected' : 'No data available',
1840
+ itemsFound: 0,
1841
+ itemsCovered: 0,
1842
+ coveragePercent: 0,
1843
+ });
1844
+ }
1845
+ }
1846
+ const manifestPath = (0, scanManifest_1.writeScanManifest)({
1847
+ projectRoot: rootDir,
1848
+ analyzedAt: new Date().toISOString(),
1849
+ discoveredFiles: {
1850
+ serviceFiles: artifacts.serviceFiles,
1851
+ testFiles: artifacts.testFiles,
1852
+ specFiles: artifacts.specs,
1853
+ },
1854
+ languages: artifacts.languages,
1855
+ frameworks: artifacts.frameworks,
1856
+ scanTypes,
1857
+ }, reportsDir);
1858
+ console.log(`Scan manifest written to: ${manifestPath}`);
1859
+ }
1860
+ catch (err) {
1861
+ warnings.push(`Scan manifest write failed: ${err instanceof Error ? err.message : String(err)}`);
1862
+ }
1626
1863
  // ── 5. Emit warnings ───────────────────────────────────────────────────
1627
1864
  for (const w of warnings) {
1628
1865
  console.warn(`[WARN] ${w}`);
@@ -34,6 +34,8 @@ export interface InferredBusinessRule {
34
34
  source_location: string;
35
35
  /** Raw matched code snippet */
36
36
  code_snippet: string;
37
+ /** Most specific identifiable terms from the condition, for accurate test matching */
38
+ specificKeywords: string[];
37
39
  }
38
40
  export interface BusinessRuleInferenceResult {
39
41
  rules: InferredBusinessRule[];
@@ -60,4 +62,10 @@ export declare function inferBusinessRules(serviceFiles: string[], warnings?: st
60
62
  * Returns the path of the written file.
61
63
  */
62
64
  export declare function writeInferredBusinessRules(result: BusinessRuleInferenceResult, reportsDir: string): string;
65
+ export declare const KEYWORD_STOP_WORDS: Set<string>;
66
+ /**
67
+ * Extract the most specific identifiable terms from a rule condition string.
68
+ * Prioritises quoted field names and message fragments over generic identifiers.
69
+ */
70
+ export declare function extractSpecificKeywords(condition: string): string[];
63
71
  //# sourceMappingURL=businessRuleInference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"businessRuleInference.d.ts","sourceRoot":"","sources":["../../../src/inference/businessRuleInference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AACjD,MAAM,MAAM,QAAQ,GAChB,YAAY,GACZ,eAAe,GACf,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA2ID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,EAAE,CA2C3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,QAAQ,GAAE,MAAM,EAAO,GACtB,2BAA2B,CAuB7B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,2BAA2B,EACnC,UAAU,EAAE,MAAM,GACjB,MAAM,CAYR"}
1
+ {"version":3,"file":"businessRuleInference.d.ts","sourceRoot":"","sources":["../../../src/inference/businessRuleInference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AACjD,MAAM,MAAM,QAAQ,GAChB,YAAY,GACZ,eAAe,GACf,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA2ID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,EAAE,CA4C3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,QAAQ,GAAE,MAAM,EAAO,GACtB,2BAA2B,CAuB7B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,2BAA2B,EACnC,UAAU,EAAE,MAAM,GACjB,MAAM,CAYR;AAID,eAAO,MAAM,kBAAkB,aAM7B,CAAC;AAEH;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAwCnE"}
@@ -50,9 +50,11 @@ var __importStar = (this && this.__importStar) || (function () {
50
50
  };
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.KEYWORD_STOP_WORDS = void 0;
53
54
  exports.inferRulesFromFile = inferRulesFromFile;
54
55
  exports.inferBusinessRules = inferBusinessRules;
55
56
  exports.writeInferredBusinessRules = writeInferredBusinessRules;
57
+ exports.extractSpecificKeywords = extractSpecificKeywords;
56
58
  const fs = __importStar(require("fs"));
57
59
  const path = __importStar(require("path"));
58
60
  const INFERENCE_PATTERNS = [
@@ -208,6 +210,7 @@ function inferRulesFromFile(filePath) {
208
210
  expected_behavior: ip.behaviorTemplate(match),
209
211
  source_location: sourceLocation,
210
212
  code_snippet: line.trim().slice(0, 200),
213
+ specificKeywords: extractSpecificKeywords(condition),
211
214
  });
212
215
  }
213
216
  }
@@ -258,6 +261,55 @@ function writeInferredBusinessRules(result, reportsDir) {
258
261
  return outputPath;
259
262
  }
260
263
  // ─── Helpers ─────────────────────────────────────────────────────────────────
264
+ exports.KEYWORD_STOP_WORDS = new Set([
265
+ 'http', 'exception', 'error', 'errors', 'throw', 'throws', 'raise', 'raises',
266
+ 'new', 'return', 'returns', 'status', 'response', 'request', 'abort',
267
+ 'the', 'and', 'for', 'with', 'that', 'this', 'from', 'not', 'has',
268
+ 'can', 'cant', 'be', 'been', 'must', 'will', 'was', 'are', 'have',
269
+ 'its', 'too', 'also', 'just', 'only', 'than', 'then', 'when',
270
+ ]);
271
+ /**
272
+ * Extract the most specific identifiable terms from a rule condition string.
273
+ * Prioritises quoted field names and message fragments over generic identifiers.
274
+ */
275
+ function extractSpecificKeywords(condition) {
276
+ var _a, _b, _c;
277
+ const kwSet = new Set();
278
+ // 1. Extract contents of quoted strings (field names, messages)
279
+ // Minimum length of 2 prevents single-character tokens like punctuation or abbreviations
280
+ // from polluting the keyword set (e.g. single-char matches from `{ e: [...] }`).
281
+ const quotedMatches = (_a = condition.match(/['"]([^'"]{2,})['"]/g)) !== null && _a !== void 0 ? _a : [];
282
+ for (const q of quotedMatches) {
283
+ const inner = q.slice(1, -1);
284
+ // Split on common separators and add each non-trivial token
285
+ inner.toLowerCase().split(/[\s\-_.,!?:;/\\]+/).forEach((tok) => {
286
+ if (tok.length >= 2 && !exports.KEYWORD_STOP_WORDS.has(tok) && /[a-z]/.test(tok)) {
287
+ kwSet.add(tok);
288
+ }
289
+ });
290
+ }
291
+ // 2. Extract object key identifiers from patterns like { fieldName: [...] }
292
+ const objKeyMatches = (_b = condition.match(/\{\s*(?:'([^']+)'|"([^"]+)"|(\w+))\s*:/g)) !== null && _b !== void 0 ? _b : [];
293
+ for (const m of objKeyMatches) {
294
+ const inner = m.replace(/^\{\s*/, '').replace(/\s*:$/, '').replace(/['"]/g, '').toLowerCase();
295
+ if (inner.length >= 2 && !exports.KEYWORD_STOP_WORDS.has(inner)) {
296
+ kwSet.add(inner);
297
+ }
298
+ }
299
+ // 3. Camel-case parts of exception / class names (e.g. "HttpException" → "http")
300
+ // but only non-stop identifiers of reasonable length
301
+ const identifiers = (_c = condition.match(/\b[A-Za-z][A-Za-z0-9]{2,}\b/g)) !== null && _c !== void 0 ? _c : [];
302
+ for (const id of identifiers) {
303
+ // Split camelCase into parts
304
+ const parts = id.replace(/([A-Z])/g, ' $1').toLowerCase().trim().split(/\s+/);
305
+ for (const part of parts) {
306
+ if (part.length >= 3 && !exports.KEYWORD_STOP_WORDS.has(part)) {
307
+ kwSet.add(part);
308
+ }
309
+ }
310
+ }
311
+ return [...kwSet];
312
+ }
261
313
  function toSnakeCase(str) {
262
314
  return str
263
315
  .replace(/([A-Z])/g, '_$1')
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Route Inference Engine
3
+ *
4
+ * Discovers HTTP routes from Express/Koa/Hapi/Fastify source files when no
5
+ * OpenAPI spec is available, enabling endpoint coverage analysis without
6
+ * a pre-authored specification.
7
+ *
8
+ * Patterns supported:
9
+ * - Express/Koa: router.get('/path', ...) / app.post('/path', ...)
10
+ * - Multi-line: router.get(\n '/path', ...) — path on next line
11
+ * - Chained: router.route('/path').get(...).post(...)
12
+ * - JSDoc route annotations: @route {GET} /path (used only when no code pattern found)
13
+ *
14
+ * Deduplication:
15
+ * - Routes are deduplicated by method:path within each file.
16
+ * - Actual code patterns take priority over JSDoc annotations.
17
+ */
18
+ export declare const HTTP_METHODS: readonly ["get", "post", "put", "patch", "delete", "head", "options"];
19
+ export type HttpMethod = typeof HTTP_METHODS[number];
20
+ export interface InferredRoute {
21
+ method: HttpMethod;
22
+ path: string;
23
+ /** Primary service function called in the route handler, if detectable */
24
+ handlerFunction?: string;
25
+ sourceFile: string;
26
+ lineNumber: number;
27
+ /** How this route was discovered */
28
+ discoveredVia: 'code' | 'jsdoc';
29
+ }
30
+ export interface RouteInferenceResult {
31
+ routes: InferredRoute[];
32
+ filesAnalyzed: number;
33
+ warnings: string[];
34
+ }
35
+ /**
36
+ * Infer routes from a single source file.
37
+ * Routes are deduplicated by method:path within the file.
38
+ * Code-based patterns take priority over JSDoc annotations for the same method+path.
39
+ */
40
+ export declare function inferRoutesFromFile(filePath: string): InferredRoute[];
41
+ /**
42
+ * Infer routes from a set of service source files.
43
+ */
44
+ export declare function inferRoutes(serviceFiles: string[]): RouteInferenceResult;
45
+ /**
46
+ * Write inferred routes to the reports directory.
47
+ * Returns the path of the written file.
48
+ */
49
+ export declare function writeInferredRoutes(result: RouteInferenceResult, reportsDir: string): string;
50
+ //# sourceMappingURL=routeInference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeInference.d.ts","sourceRoot":"","sources":["../../../src/inference/routeInference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,eAAO,MAAM,YAAY,uEAAwE,CAAC;AAClG,MAAM,MAAM,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAoDD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAiFrE;AAiBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAgBxE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAY5F"}