brakit 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,26 @@
1
- (function(){'use strict';var Rs=Object.defineProperty;var ws=Object.getOwnPropertyDescriptor;var u=(i,e,t,s)=>{for(var r=s>1?void 0:s?ws(e,t):e,o=i.length-1,n;o>=0;o--)(n=i[o])&&(r=(s?n(e,t,r):n(r))||r);return s&&r&&Rs(e,t,r),r};var Lt=globalThis,Ot=Lt.ShadowRoot&&(Lt.ShadyCSS===void 0||Lt.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,xe=Symbol(),ye=new WeakMap,Mt=class{constructor(e,t,s){if(this._$cssResult$=true,s!==xe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t;}get styleSheet(){let e=this.o,t=this.t;if(Ot&&e===void 0){let s=t!==void 0&&t.length===1;s&&(e=ye.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),s&&ye.set(t,e));}return e}toString(){return this.cssText}},Re=i=>new Mt(typeof i=="string"?i:i+"",void 0,xe);var we=(i,e)=>{if(Ot)i.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(let t of e){let s=document.createElement("style"),r=Lt.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=t.cssText,i.appendChild(s);}},Qt=Ot?i=>i:i=>i instanceof CSSStyleSheet?(e=>{let t="";for(let s of e.cssRules)t+=s.cssText;return Re(t)})(i):i;var{is:As,defineProperty:Cs,getOwnPropertyDescriptor:Is,getOwnPropertyNames:Ls,getOwnPropertySymbols:Ms,getPrototypeOf:Os}=Object,k=globalThis,Ae=k.trustedTypes,Ns=Ae?Ae.emptyScript:"",ks=k.reactiveElementPolyfillSupport,ht=(i,e)=>i,mt={toAttribute(i,e){switch(e){case Boolean:i=i?Ns:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i);}return i},fromAttribute(i,e){let t=i;switch(e){case Boolean:t=i!==null;break;case Number:t=i===null?null:Number(i);break;case Object:case Array:try{t=JSON.parse(i);}catch{t=null;}}return t}},Nt=(i,e)=>!As(i,e),Ce={attribute:true,type:String,converter:mt,reflect:false,useDefault:false,hasChanged:Nt};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),k.litPropertyMetadata??(k.litPropertyMetadata=new WeakMap);var O=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??(this.l=[])).push(e);}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=Ce){if(t.state&&(t.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=true),this.elementProperties.set(e,t),!t.noAccessor){let s=Symbol(),r=this.getPropertyDescriptor(e,s,t);r!==void 0&&Cs(this.prototype,e,r);}}static getPropertyDescriptor(e,t,s){let{get:r,set:o}=Is(this.prototype,e)??{get(){return this[t]},set(n){this[t]=n;}};return {get:r,set(n){let l=r?.call(this);o?.call(this,n),this.requestUpdate(e,l,s);},configurable:true,enumerable:true}}static getPropertyOptions(e){return this.elementProperties.get(e)??Ce}static _$Ei(){if(this.hasOwnProperty(ht("elementProperties")))return;let e=Os(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties);}static finalize(){if(this.hasOwnProperty(ht("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(ht("properties"))){let t=this.properties,s=[...Ls(t),...Ms(t)];for(let r of s)this.createProperty(r,t[r]);}let e=this[Symbol.metadata];if(e!==null){let t=litPropertyMetadata.get(e);if(t!==void 0)for(let[s,r]of t)this.elementProperties.set(s,r);}this._$Eh=new Map;for(let[t,s]of this.elementProperties){let r=this._$Eu(t,s);r!==void 0&&this._$Eh.set(r,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let s=new Set(e.flat(1/0).reverse());for(let r of s)t.unshift(Qt(r));}else e!==void 0&&t.push(Qt(e));return t}static _$Eu(e,t){let s=t.attribute;return s===false?void 0:typeof s=="string"?s:typeof e=="string"?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,this._$Em=null,this._$Ev();}_$Ev(){this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this));}addController(e){(this._$EO??(this._$EO=new Set)).add(e),this.renderRoot!==void 0&&this.isConnected&&e.hostConnected?.();}removeController(e){this._$EO?.delete(e);}_$E_(){let e=new Map,t=this.constructor.elementProperties;for(let s of t.keys())this.hasOwnProperty(s)&&(e.set(s,this[s]),delete this[s]);e.size>0&&(this._$Ep=e);}createRenderRoot(){let e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return we(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(true),this._$EO?.forEach(e=>e.hostConnected?.());}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.());}attributeChangedCallback(e,t,s){this._$AK(e,s);}_$ET(e,t){let s=this.constructor.elementProperties.get(e),r=this.constructor._$Eu(e,s);if(r!==void 0&&s.reflect===true){let o=(s.converter?.toAttribute!==void 0?s.converter:mt).toAttribute(t,s.type);this._$Em=e,o==null?this.removeAttribute(r):this.setAttribute(r,o),this._$Em=null;}}_$AK(e,t){let s=this.constructor,r=s._$Eh.get(e);if(r!==void 0&&this._$Em!==r){let o=s.getPropertyOptions(r),n=typeof o.converter=="function"?{fromAttribute:o.converter}:o.converter?.fromAttribute!==void 0?o.converter:mt;this._$Em=r;let l=n.fromAttribute(t,o.type);this[r]=l??this._$Ej?.get(r)??l,this._$Em=null;}}requestUpdate(e,t,s,r=false,o){if(e!==void 0){let n=this.constructor;if(r===false&&(o=this[e]),s??(s=n.getPropertyOptions(e)),!((s.hasChanged??Nt)(o,t)||s.useDefault&&s.reflect&&o===this._$Ej?.get(e)&&!this.hasAttribute(n._$Eu(e,s))))return;this.C(e,t,s);}this.isUpdatePending===false&&(this._$ES=this._$EP());}C(e,t,{useDefault:s,reflect:r,wrapped:o},n){s&&!(this._$Ej??(this._$Ej=new Map)).has(e)&&(this._$Ej.set(e,n??t??this[e]),o!==true||n!==void 0)||(this._$AL.has(e)||(this.hasUpdated||s||(t=void 0),this._$AL.set(e,t)),r===true&&this._$Em!==e&&(this._$Eq??(this._$Eq=new Set)).add(e));}async _$EP(){this.isUpdatePending=true;try{await this._$ES;}catch(t){Promise.reject(t);}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(let[r,o]of this._$Ep)this[r]=o;this._$Ep=void 0;}let s=this.constructor.elementProperties;if(s.size>0)for(let[r,o]of s){let{wrapped:n}=o,l=this[r];n!==true||this._$AL.has(r)||l===void 0||this.C(r,void 0,o,l);}}let e=false,t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(t)):this._$EM();}catch(s){throw e=false,this._$EM(),s}e&&this._$AE(t);}willUpdate(e){}_$AE(e){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(e)),this.updated(e);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return true}update(e){this._$Eq&&(this._$Eq=this._$Eq.forEach(t=>this._$ET(t,this[t]))),this._$EM();}updated(e){}firstUpdated(e){}};O.elementStyles=[],O.shadowRootOptions={mode:"open"},O[ht("elementProperties")]=new Map,O[ht("finalized")]=new Map,ks?.({ReactiveElement:O}),(k.reactiveElementVersions??(k.reactiveElementVersions=[])).push("2.1.2");var ft=globalThis,Ie=i=>i,kt=ft.trustedTypes,Le=kt?kt.createPolicy("lit-html",{createHTML:i=>i}):void 0,He="$lit$",D=`lit$${Math.random().toFixed(9).slice(2)}$`,qe="?"+D,Ds=`<${qe}>`,W=document,gt=()=>W.createComment(""),Et=i=>i===null||typeof i!="object"&&typeof i!="function",Zt=Array.isArray,Hs=i=>Zt(i)||typeof i?.[Symbol.iterator]=="function",Vt=`[
2
- \f\r]`,vt=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Me=/-->/g,Oe=/>/g,B=RegExp(`>|${Vt}(?:([^\\s"'>=/]+)(${Vt}*=${Vt}*(?:[^
3
- \f\r"'\`<>=]|("|')|))|$)`,"g"),Ne=/'/g,ke=/"/g,Pe=/^(?:script|style|textarea|title)$/i,te=i=>(e,...t)=>({_$litType$:i,strings:e,values:t}),a=te(1),j=Symbol.for("lit-noChange"),d=Symbol.for("lit-nothing"),De=new WeakMap,G=W.createTreeWalker(W,129);function Ue(i,e){if(!Zt(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return Le!==void 0?Le.createHTML(e):e}var qs=(i,e)=>{let t=i.length-1,s=[],r,o=e===2?"<svg>":e===3?"<math>":"",n=vt;for(let l=0;l<t;l++){let c=i[l],p,h,m=-1,E=0;for(;E<c.length&&(n.lastIndex=E,h=n.exec(c),h!==null);)E=n.lastIndex,n===vt?h[1]==="!--"?n=Me:h[1]!==void 0?n=Oe:h[2]!==void 0?(Pe.test(h[2])&&(r=RegExp("</"+h[2],"g")),n=B):h[3]!==void 0&&(n=B):n===B?h[0]===">"?(n=r??vt,m=-1):h[1]===void 0?m=-2:(m=n.lastIndex-h[2].length,p=h[1],n=h[3]===void 0?B:h[3]==='"'?ke:Ne):n===ke||n===Ne?n=B:n===Me||n===Oe?n=vt:(n=B,r=void 0);let T=n===B&&i[l+1].startsWith("/>")?" ":"";o+=n===vt?c+Ds:m>=0?(s.push(p),c.slice(0,m)+He+c.slice(m)+D+T):c+D+(m===-2?l:T);}return [Ue(i,o+(i[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),s]},bt=class i{constructor({strings:e,_$litType$:t},s){let r;this.parts=[];let o=0,n=0,l=e.length-1,c=this.parts,[p,h]=qs(e,t);if(this.el=i.createElement(p,s),G.currentNode=this.el.content,t===2||t===3){let m=this.el.content.firstChild;m.replaceWith(...m.childNodes);}for(;(r=G.nextNode())!==null&&c.length<l;){if(r.nodeType===1){if(r.hasAttributes())for(let m of r.getAttributeNames())if(m.endsWith(He)){let E=h[n++],T=r.getAttribute(m).split(D),b=/([.?@])?(.*)/.exec(E);c.push({type:1,index:o,name:b[2],strings:T,ctor:b[1]==="."?Xt:b[1]==="?"?Kt:b[1]==="@"?zt:z}),r.removeAttribute(m);}else m.startsWith(D)&&(c.push({type:6,index:o}),r.removeAttribute(m));if(Pe.test(r.tagName)){let m=r.textContent.split(D),E=m.length-1;if(E>0){r.textContent=kt?kt.emptyScript:"";for(let T=0;T<E;T++)r.append(m[T],gt()),G.nextNode(),c.push({type:2,index:++o});r.append(m[E],gt());}}}else if(r.nodeType===8)if(r.data===qe)c.push({type:2,index:o});else {let m=-1;for(;(m=r.data.indexOf(D,m+1))!==-1;)c.push({type:7,index:o}),m+=D.length-1;}o++;}}static createElement(e,t){let s=W.createElement("template");return s.innerHTML=e,s}};function K(i,e,t=i,s){if(e===j)return e;let r=s!==void 0?t._$Co?.[s]:t._$Cl,o=Et(e)?void 0:e._$litDirective$;return r?.constructor!==o&&(r?._$AO?.(false),o===void 0?r=void 0:(r=new o(i),r._$AT(i,t,s)),s!==void 0?(t._$Co??(t._$Co=[]))[s]=r:t._$Cl=r),r!==void 0&&(e=K(i,r._$AS(i,e.values),r,s)),e}var Yt=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:s}=this._$AD,r=(e?.creationScope??W).importNode(t,true);G.currentNode=r;let o=G.nextNode(),n=0,l=0,c=s[0];for(;c!==void 0;){if(n===c.index){let p;c.type===2?p=new _t(o,o.nextSibling,this,e):c.type===1?p=new c.ctor(o,c.name,c.strings,this,e):c.type===6&&(p=new Jt(o,this,e)),this._$AV.push(p),c=s[++l];}n!==c?.index&&(o=G.nextNode(),n++);}return G.currentNode=W,r}p(e){let t=0;for(let s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(e,s,t),t+=s.strings.length-2):s._$AI(e[t])),t++;}},_t=class i{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,s,r){this.type=2,this._$AH=d,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=s,this.options=r,this._$Cv=r?.isConnected??true;}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=K(this,e,t),Et(e)?e===d||e==null||e===""?(this._$AH!==d&&this._$AR(),this._$AH=d):e!==this._$AH&&e!==j&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):Hs(e)?this.k(e):this._(e);}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e));}_(e){this._$AH!==d&&Et(this._$AH)?this._$AA.nextSibling.data=e:this.T(W.createTextNode(e)),this._$AH=e;}$(e){let{values:t,_$litType$:s}=e,r=typeof s=="number"?this._$AC(e):(s.el===void 0&&(s.el=bt.createElement(Ue(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===r)this._$AH.p(t);else {let o=new Yt(r,this),n=o.u(this.options);o.p(t),this.T(n),this._$AH=o;}}_$AC(e){let t=De.get(e.strings);return t===void 0&&De.set(e.strings,t=new bt(e)),t}k(e){Zt(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,s,r=0;for(let o of e)r===t.length?t.push(s=new i(this.O(gt()),this.O(gt()),this,this.options)):s=t[r],s._$AI(o),r++;r<t.length&&(this._$AR(s&&s._$AB.nextSibling,r),t.length=r);}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(false,true,t);e!==this._$AB;){let s=Ie(e).nextSibling;Ie(e).remove(),e=s;}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e));}},z=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,s,r,o){this.type=1,this._$AH=d,this._$AN=void 0,this.element=e,this.name=t,this._$AM=r,this.options=o,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=d;}_$AI(e,t=this,s,r){let o=this.strings,n=false;if(o===void 0)e=K(this,e,t,0),n=!Et(e)||e!==this._$AH&&e!==j,n&&(this._$AH=e);else {let l=e,c,p;for(e=o[0],c=0;c<o.length-1;c++)p=K(this,l[s+c],t,c),p===j&&(p=this._$AH[c]),n||(n=!Et(p)||p!==this._$AH[c]),p===d?e=d:e!==d&&(e+=(p??"")+o[c+1]),this._$AH[c]=p;}n&&!r&&this.j(e);}j(e){e===d?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"");}},Xt=class extends z{constructor(){super(...arguments),this.type=3;}j(e){this.element[this.name]=e===d?void 0:e;}},Kt=class extends z{constructor(){super(...arguments),this.type=4;}j(e){this.element.toggleAttribute(this.name,!!e&&e!==d);}},zt=class extends z{constructor(e,t,s,r,o){super(e,t,s,r,o),this.type=5;}_$AI(e,t=this){if((e=K(this,e,t,0)??d)===j)return;let s=this._$AH,r=e===d&&s!==d||e.capture!==s.capture||e.once!==s.once||e.passive!==s.passive,o=e!==d&&(s===d||r);r&&this.element.removeEventListener(this.name,this,s),o&&this.element.addEventListener(this.name,this,e),this._$AH=e;}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e);}},Jt=class{constructor(e,t,s){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(e){K(this,e);}};var Ps=ft.litHtmlPolyfillSupport;Ps?.(bt,_t),(ft.litHtmlVersions??(ft.litHtmlVersions=[])).push("3.3.2");var Fe=(i,e,t)=>{let s=t?.renderBefore??e,r=s._$litPart$;if(r===void 0){let o=t?.renderBefore??null;s._$litPart$=r=new _t(e.insertBefore(gt(),o),o,void 0,t??{});}return r._$AI(i),r};var St=globalThis,f=class extends O{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){var t;let e=super.createRenderRoot();return (t=this.renderOptions).renderBefore??(t.renderBefore=e.firstChild),e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=Fe(t,this.renderRoot,this.renderOptions);}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(true);}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(false);}render(){return j}};f._$litElement$=true,f.finalized=true,St.litElementHydrateSupport?.({LitElement:f});var Us=St.litElementPolyfillSupport;Us?.({LitElement:f});(St.litElementVersions??(St.litElementVersions=[])).push("4.2.2");var g=i=>(e,t)=>{t!==void 0?t.addInitializer(()=>{customElements.define(i,e);}):customElements.define(i,e);};var Fs={attribute:true,type:String,converter:mt,reflect:false,hasChanged:Nt},Bs=(i=Fs,e,t)=>{let{kind:s,metadata:r}=t,o=globalThis.litPropertyMetadata.get(r);if(o===void 0&&globalThis.litPropertyMetadata.set(r,o=new Map),s==="setter"&&((i=Object.create(i)).wrapped=true),o.set(t.name,i),s==="accessor"){let{name:n}=t;return {set(l){let c=e.get.call(this);e.set.call(this,l),this.requestUpdate(n,c,i,true,l);},init(l){return l!==void 0&&this.C(n,void 0,i,l),l}}}if(s==="setter"){let{name:n}=t;return function(l){let c=this[n];e.call(this,l),this.requestUpdate(n,c,i,true,l);}}throw Error("Unsupported decorator location: "+s)};function y(i){return (e,t)=>typeof t=="object"?Bs(i,e,t):((s,r,o)=>{let n=r.hasOwnProperty(o);return r.constructor.createProperty(o,s),n?Object.getOwnPropertyDescriptor(r,o):void 0})(i,e,t)}function _(i){return y({...i,state:true,attribute:false})}var Tt=class extends f{constructor(){super(...arguments);this.method="";}createRenderRoot(){return this}render(){let t=this.method.toUpperCase();return a`<span class="method-badge method-badge-${t}">${t}</span>`}};u([y()],Tt.prototype,"method",2),Tt=u([g("bk-method-badge")],Tt);var I="/__brakit/api",N="/__brakit",$={flows:`${I}/flows`,requests:`${I}/requests`,events:`${I}/events`,clear:`${I}/clear`,fetches:`${I}/fetches`,errors:`${I}/errors`,logs:`${I}/logs`,queries:`${I}/queries`,metricsLive:`${I}/metrics/live`,insights:`${I}/insights`,tab:`${I}/tab`,activity:`${I}/activity`};var J="polling",Ht="static",Gs="auth-handshake",Ws="auth-check",js="middleware",$t={[Gs]:1,[Ws]:1,[js]:1};var ee="fetch";var se="error_event",re="query",oe="issues";var ie={overview:"Overview",actions:"Actions",requests:"Requests",fetches:"Server Fetches",queries:"Queries",errors:"Errors",logs:"Logs",performance:"Performance",security:"Security"},ne={overview:"Live summary of your application",actions:"User actions captured as sequences of HTTP requests",requests:"All HTTP requests proxied through brakit",fetches:"Outbound HTTP calls made by your server to external services",queries:"Database queries executed during request handling",errors:"Unhandled exceptions and errors thrown by your application",logs:"Console output from your application",performance:"Endpoint health and response time trends",security:"Security findings and recommendations"};var le=100,Z=300,tt=800,ce=2e3,de=100,pe=50,ue=500;var H="__all__",Ft={SELECT:"var(--blue)",INSERT:"var(--green)",UPDATE:"var(--amber)",DELETE:"var(--red)",COUNT:"var(--text-muted)"},Ke={error:"var(--red)",warn:"var(--amber)",info:"var(--blue)",debug:"var(--text-muted)",log:"var(--text-dim)"},me=["#2563eb","#7c3aed","#16a34a","#d97706","#dc2626","#0891b2","#ea580c","#c026d3","#059669","#db2777"],yt={green:"#4ade80",amber:"#fbbf24",red:"#f87171"},et=[{max:le,label:"Fast",color:"var(--green)",bg:"rgba(22,163,74,0.08)",border:"rgba(22,163,74,0.2)"},{max:Z,label:"Good",color:"var(--green)",bg:"rgba(22,163,74,0.06)",border:"rgba(22,163,74,0.15)"},{max:tt,label:"OK",color:"var(--amber)",bg:"rgba(217,119,6,0.06)",border:"rgba(217,119,6,0.15)"},{max:ce,label:"Slow",color:"var(--red)",bg:"rgba(220,38,38,0.06)",border:"rgba(220,38,38,0.15)"},{max:1/0,label:"Critical",color:"var(--red)",bg:"rgba(220,38,38,0.08)",border:"rgba(220,38,38,0.2)"}],ze="rgba(228,228,231,0.8)",ve="rgba(113,113,122,0.7)",Je="10px monospace",fe="9px monospace";var Ze={top:16,right:16,bottom:28,left:52},ts={fetch:"var(--blue)",log:"var(--text-muted)",error:"var(--red)",query:"var(--accent)"},es={fetch:"FETCH",log:"LOG",error:"ERROR",query:"QUERY"},ss=new Set(["cookie","set-cookie","authorization","proxy-authorization","x-api-key","x-auth-token"]),rs={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",408:"Timeout",409:"Conflict",422:"Unprocessable",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},os=new Set(["host","connection","accept-encoding"]),q={critical:{icon:"\u2717",cls:"critical",sort:0},warning:{icon:"\u26A0",cls:"warning",sort:1},info:{icon:"\u2139",cls:"info",sort:2}};function v(i){return i<1e3?i+"ms":(i/1e3).toFixed(1)+"s"}function U(i){return !i||i===0?"":i<1024?i+"b":(i/1024).toFixed(1)+"kb"}function P(i){return i?i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function st(i){return i>=500?"status-pill-5xx":i>=400?"status-pill-4xx":i>=300?"status-pill-3xx":"status-pill-2xx"}function is(i){return rs[i]||(i>=500?"Server Error":i>=400?"Client Error":"OK")}function Qs(i,e){if(ss.has(i.toLowerCase())){let t=String(e);return t.length<=8?"****":t.slice(0,4)+"..."+t.slice(-4)+" ("+t.length+" chars)"}return String(e)}function rt(i){return !i||Object.keys(i).length===0?'<span style="color:var(--text-muted)">No headers</span>':Object.entries(i).map(([e,t])=>'<span class="json-key">'+P(e)+"</span>: "+P(Qs(e,t))).join(`
4
- `)}function Q(i){if(!i)return '<span style="color:var(--text-muted)">No body</span>';try{let e=JSON.parse(i);return Vs(JSON.stringify(e,null,2))}catch{return P(i)}}function Vs(i){return P(i).replace(/("(?:[^"\\]|\\.)*")(\s*:)?|\b(true|false)\b|\bnull\b|(-?\d+\.?\d*(?:[eE][+-]?\d+)?)/g,(e,t,s,r,o)=>t?s?'<span class="json-key">'+t+"</span>"+s:'<span class="json-str">'+t+"</span>":r?'<span class="json-bool">'+e+"</span>":o?'<span class="json-num">'+e+"</span>":e==="null"?'<span class="json-null">null</span>':e)}var xt=class extends f{constructor(){super(...arguments);this.code=0;}createRenderRoot(){return this}render(){let t=st(this.code);return a`<span class="status-pill ${t}">${this.code}</span>`}};u([y({type:Number})],xt.prototype,"code",2),xt=u([g("bk-status-pill")],xt);var Rt=class extends f{constructor(){super(...arguments);this.ms=0;}createRenderRoot(){return this}render(){return a`<span class="req-duration">${v(this.ms)}</span>`}};u([y({type:Number})],Rt.prototype,"ms",2),Rt=u([g("bk-duration-label")],Rt);var ot=class extends f{constructor(){super(...arguments);this.title="";this.subtitle="";}createRenderRoot(){return this}render(){return a`
1
+ (function(){'use strict';var wr=Object.defineProperty;var Rr=Object.getOwnPropertyDescriptor;var u=(o,s,t,e)=>{for(var r=e>1?void 0:e?Rr(s,t):s,i=o.length-1,n;i>=0;i--)(n=o[i])&&(r=(e?n(s,t,r):n(r))||r);return e&&r&&wr(s,t,r),r};var zt=globalThis,Zt=zt.ShadowRoot&&(zt.ShadyCSS===void 0||zt.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,os=Symbol(),is=new WeakMap,Jt=class{constructor(s,t,e){if(this._$cssResult$=true,e!==os)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=s,this.t=t;}get styleSheet(){let s=this.o,t=this.t;if(Zt&&s===void 0){let e=t!==void 0&&t.length===1;e&&(s=is.get(t)),s===void 0&&((this.o=s=new CSSStyleSheet).replaceSync(this.cssText),e&&is.set(t,s));}return s}toString(){return this.cssText}},ns=o=>new Jt(typeof o=="string"?o:o+"",void 0,os);var as=(o,s)=>{if(Zt)o.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(let t of s){let e=document.createElement("style"),r=zt.litNonce;r!==void 0&&e.setAttribute("nonce",r),e.textContent=t.cssText,o.appendChild(e);}},ye=Zt?o=>o:o=>o instanceof CSSStyleSheet?(s=>{let t="";for(let e of s.cssRules)t+=e.cssText;return ns(t)})(o):o;var{is:Ar,defineProperty:Ir,getOwnPropertyDescriptor:Cr,getOwnPropertyNames:Lr,getOwnPropertySymbols:Mr,getPrototypeOf:Nr}=Object,K=globalThis,ls=K.trustedTypes,Or=ls?ls.emptyScript:"",kr=K.reactiveElementPolyfillSupport,Mt=(o,s)=>o,Nt={toAttribute(o,s){switch(s){case Boolean:o=o?Or:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o);}return o},fromAttribute(o,s){let t=o;switch(s){case Boolean:t=o!==null;break;case Number:t=o===null?null:Number(o);break;case Object:case Array:try{t=JSON.parse(o);}catch{t=null;}}return t}},te=(o,s)=>!Ar(o,s),cs={attribute:true,type:String,converter:Nt,reflect:false,useDefault:false,hasChanged:te};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),K.litPropertyMetadata??(K.litPropertyMetadata=new WeakMap);var j=class extends HTMLElement{static addInitializer(s){this._$Ei(),(this.l??(this.l=[])).push(s);}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(s,t=cs){if(t.state&&(t.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(s)&&((t=Object.create(t)).wrapped=true),this.elementProperties.set(s,t),!t.noAccessor){let e=Symbol(),r=this.getPropertyDescriptor(s,e,t);r!==void 0&&Ir(this.prototype,s,r);}}static getPropertyDescriptor(s,t,e){let{get:r,set:i}=Cr(this.prototype,s)??{get(){return this[t]},set(n){this[t]=n;}};return {get:r,set(n){let l=r?.call(this);i?.call(this,n),this.requestUpdate(s,l,e);},configurable:true,enumerable:true}}static getPropertyOptions(s){return this.elementProperties.get(s)??cs}static _$Ei(){if(this.hasOwnProperty(Mt("elementProperties")))return;let s=Nr(this);s.finalize(),s.l!==void 0&&(this.l=[...s.l]),this.elementProperties=new Map(s.elementProperties);}static finalize(){if(this.hasOwnProperty(Mt("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(Mt("properties"))){let t=this.properties,e=[...Lr(t),...Mr(t)];for(let r of e)this.createProperty(r,t[r]);}let s=this[Symbol.metadata];if(s!==null){let t=litPropertyMetadata.get(s);if(t!==void 0)for(let[e,r]of t)this.elementProperties.set(e,r);}this._$Eh=new Map;for(let[t,e]of this.elementProperties){let r=this._$Eu(t,e);r!==void 0&&this._$Eh.set(r,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(s){let t=[];if(Array.isArray(s)){let e=new Set(s.flat(1/0).reverse());for(let r of e)t.unshift(ye(r));}else s!==void 0&&t.push(ye(s));return t}static _$Eu(s,t){let e=t.attribute;return e===false?void 0:typeof e=="string"?e:typeof s=="string"?s.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,this._$Em=null,this._$Ev();}_$Ev(){this._$ES=new Promise(s=>this.enableUpdating=s),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(s=>s(this));}addController(s){(this._$EO??(this._$EO=new Set)).add(s),this.renderRoot!==void 0&&this.isConnected&&s.hostConnected?.();}removeController(s){this._$EO?.delete(s);}_$E_(){let s=new Map,t=this.constructor.elementProperties;for(let e of t.keys())this.hasOwnProperty(e)&&(s.set(e,this[e]),delete this[e]);s.size>0&&(this._$Ep=s);}createRenderRoot(){let s=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return as(s,this.constructor.elementStyles),s}connectedCallback(){this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(true),this._$EO?.forEach(s=>s.hostConnected?.());}enableUpdating(s){}disconnectedCallback(){this._$EO?.forEach(s=>s.hostDisconnected?.());}attributeChangedCallback(s,t,e){this._$AK(s,e);}_$ET(s,t){let e=this.constructor.elementProperties.get(s),r=this.constructor._$Eu(s,e);if(r!==void 0&&e.reflect===true){let i=(e.converter?.toAttribute!==void 0?e.converter:Nt).toAttribute(t,e.type);this._$Em=s,i==null?this.removeAttribute(r):this.setAttribute(r,i),this._$Em=null;}}_$AK(s,t){let e=this.constructor,r=e._$Eh.get(s);if(r!==void 0&&this._$Em!==r){let i=e.getPropertyOptions(r),n=typeof i.converter=="function"?{fromAttribute:i.converter}:i.converter?.fromAttribute!==void 0?i.converter:Nt;this._$Em=r;let l=n.fromAttribute(t,i.type);this[r]=l??this._$Ej?.get(r)??l,this._$Em=null;}}requestUpdate(s,t,e,r=false,i){if(s!==void 0){let n=this.constructor;if(r===false&&(i=this[s]),e??(e=n.getPropertyOptions(s)),!((e.hasChanged??te)(i,t)||e.useDefault&&e.reflect&&i===this._$Ej?.get(s)&&!this.hasAttribute(n._$Eu(s,e))))return;this.C(s,t,e);}this.isUpdatePending===false&&(this._$ES=this._$EP());}C(s,t,{useDefault:e,reflect:r,wrapped:i},n){e&&!(this._$Ej??(this._$Ej=new Map)).has(s)&&(this._$Ej.set(s,n??t??this[s]),i!==true||n!==void 0)||(this._$AL.has(s)||(this.hasUpdated||e||(t=void 0),this._$AL.set(s,t)),r===true&&this._$Em!==s&&(this._$Eq??(this._$Eq=new Set)).add(s));}async _$EP(){this.isUpdatePending=true;try{await this._$ES;}catch(t){Promise.reject(t);}let s=this.scheduleUpdate();return s!=null&&await s,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(let[r,i]of this._$Ep)this[r]=i;this._$Ep=void 0;}let e=this.constructor.elementProperties;if(e.size>0)for(let[r,i]of e){let{wrapped:n}=i,l=this[r];n!==true||this._$AL.has(r)||l===void 0||this.C(r,void 0,i,l);}}let s=false,t=this._$AL;try{s=this.shouldUpdate(t),s?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM();}catch(e){throw s=false,this._$EM(),e}s&&this._$AE(t);}willUpdate(s){}_$AE(s){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(s)),this.updated(s);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(s){return true}update(s){this._$Eq&&(this._$Eq=this._$Eq.forEach(t=>this._$ET(t,this[t]))),this._$EM();}updated(s){}firstUpdated(s){}};j.elementStyles=[],j.shadowRootOptions={mode:"open"},j[Mt("elementProperties")]=new Map,j[Mt("finalized")]=new Map,kr?.({ReactiveElement:j}),(K.reactiveElementVersions??(K.reactiveElementVersions=[])).push("2.1.2");var kt=globalThis,ds=o=>o,ee=kt.trustedTypes,ps=ee?ee.createPolicy("lit-html",{createHTML:o=>o}):void 0,gs="$lit$",z=`lit$${Math.random().toFixed(9).slice(2)}$`,bs="?"+z,Dr=`<${bs}>`,ot=document,Dt=()=>ot.createComment(""),Ht=o=>o===null||typeof o!="object"&&typeof o!="function",Re=Array.isArray,Hr=o=>Re(o)||typeof o?.[Symbol.iterator]=="function",_e=`[
2
+ \f\r]`,Ot=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,hs=/-->/g,us=/>/g,rt=RegExp(`>|${_e}(?:([^\\s"'>=/]+)(${_e}*=${_e}*(?:[^
3
+ \f\r"'\`<>=]|("|')|))|$)`,"g"),ms=/'/g,fs=/"/g,Es=/^(?:script|style|textarea|title)$/i,Ae=o=>(s,...t)=>({_$litType$:o,strings:s,values:t}),a=Ae(1),O=Ae(2),Y=Symbol.for("lit-noChange"),p=Symbol.for("lit-nothing"),vs=new WeakMap,it=ot.createTreeWalker(ot,129);function ys(o,s){if(!Re(o)||!o.hasOwnProperty("raw"))throw Error("invalid template strings array");return ps!==void 0?ps.createHTML(s):s}var Pr=(o,s)=>{let t=o.length-1,e=[],r,i=s===2?"<svg>":s===3?"<math>":"",n=Ot;for(let l=0;l<t;l++){let c=o[l],d,h,m=-1,v=0;for(;v<c.length&&(n.lastIndex=v,h=n.exec(c),h!==null);)v=n.lastIndex,n===Ot?h[1]==="!--"?n=hs:h[1]!==void 0?n=us:h[2]!==void 0?(Es.test(h[2])&&(r=RegExp("</"+h[2],"g")),n=rt):h[3]!==void 0&&(n=rt):n===rt?h[0]===">"?(n=r??Ot,m=-1):h[1]===void 0?m=-2:(m=n.lastIndex-h[2].length,d=h[1],n=h[3]===void 0?rt:h[3]==='"'?fs:ms):n===fs||n===ms?n=rt:n===hs||n===us?n=Ot:(n=rt,r=void 0);let x=n===rt&&o[l+1].startsWith("/>")?" ":"";i+=n===Ot?c+Dr:m>=0?(e.push(d),c.slice(0,m)+gs+c.slice(m)+z+x):c+z+(m===-2?l:x);}return [ys(o,i+(o[t]||"<?>")+(s===2?"</svg>":s===3?"</math>":"")),e]},Pt=class o{constructor({strings:s,_$litType$:t},e){let r;this.parts=[];let i=0,n=0,l=s.length-1,c=this.parts,[d,h]=Pr(s,t);if(this.el=o.createElement(d,e),it.currentNode=this.el.content,t===2||t===3){let m=this.el.content.firstChild;m.replaceWith(...m.childNodes);}for(;(r=it.nextNode())!==null&&c.length<l;){if(r.nodeType===1){if(r.hasAttributes())for(let m of r.getAttributeNames())if(m.endsWith(gs)){let v=h[n++],x=r.getAttribute(m).split(z),y=/([.?@])?(.*)/.exec(v);c.push({type:1,index:i,name:y[2],strings:x,ctor:y[1]==="."?xe:y[1]==="?"?Se:y[1]==="@"?Te:ht}),r.removeAttribute(m);}else m.startsWith(z)&&(c.push({type:6,index:i}),r.removeAttribute(m));if(Es.test(r.tagName)){let m=r.textContent.split(z),v=m.length-1;if(v>0){r.textContent=ee?ee.emptyScript:"";for(let x=0;x<v;x++)r.append(m[x],Dt()),it.nextNode(),c.push({type:2,index:++i});r.append(m[v],Dt());}}}else if(r.nodeType===8)if(r.data===bs)c.push({type:2,index:i});else {let m=-1;for(;(m=r.data.indexOf(z,m+1))!==-1;)c.push({type:7,index:i}),m+=z.length-1;}i++;}}static createElement(s,t){let e=ot.createElement("template");return e.innerHTML=s,e}};function pt(o,s,t=o,e){if(s===Y)return s;let r=e!==void 0?t._$Co?.[e]:t._$Cl,i=Ht(s)?void 0:s._$litDirective$;return r?.constructor!==i&&(r?._$AO?.(false),i===void 0?r=void 0:(r=new i(o),r._$AT(o,t,e)),e!==void 0?(t._$Co??(t._$Co=[]))[e]=r:t._$Cl=r),r!==void 0&&(s=pt(o,r._$AS(o,s.values),r,e)),s}var $e=class{constructor(s,t){this._$AV=[],this._$AN=void 0,this._$AD=s,this._$AM=t;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(s){let{el:{content:t},parts:e}=this._$AD,r=(s?.creationScope??ot).importNode(t,true);it.currentNode=r;let i=it.nextNode(),n=0,l=0,c=e[0];for(;c!==void 0;){if(n===c.index){let d;c.type===2?d=new qt(i,i.nextSibling,this,s):c.type===1?d=new c.ctor(i,c.name,c.strings,this,s):c.type===6&&(d=new we(i,this,s)),this._$AV.push(d),c=e[++l];}n!==c?.index&&(i=it.nextNode(),n++);}return it.currentNode=ot,r}p(s){let t=0;for(let e of this._$AV)e!==void 0&&(e.strings!==void 0?(e._$AI(s,e,t),t+=e.strings.length-2):e._$AI(s[t])),t++;}},qt=class o{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(s,t,e,r){this.type=2,this._$AH=p,this._$AN=void 0,this._$AA=s,this._$AB=t,this._$AM=e,this.options=r,this._$Cv=r?.isConnected??true;}get parentNode(){let s=this._$AA.parentNode,t=this._$AM;return t!==void 0&&s?.nodeType===11&&(s=t.parentNode),s}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(s,t=this){s=pt(this,s,t),Ht(s)?s===p||s==null||s===""?(this._$AH!==p&&this._$AR(),this._$AH=p):s!==this._$AH&&s!==Y&&this._(s):s._$litType$!==void 0?this.$(s):s.nodeType!==void 0?this.T(s):Hr(s)?this.k(s):this._(s);}O(s){return this._$AA.parentNode.insertBefore(s,this._$AB)}T(s){this._$AH!==s&&(this._$AR(),this._$AH=this.O(s));}_(s){this._$AH!==p&&Ht(this._$AH)?this._$AA.nextSibling.data=s:this.T(ot.createTextNode(s)),this._$AH=s;}$(s){let{values:t,_$litType$:e}=s,r=typeof e=="number"?this._$AC(s):(e.el===void 0&&(e.el=Pt.createElement(ys(e.h,e.h[0]),this.options)),e);if(this._$AH?._$AD===r)this._$AH.p(t);else {let i=new $e(r,this),n=i.u(this.options);i.p(t),this.T(n),this._$AH=i;}}_$AC(s){let t=vs.get(s.strings);return t===void 0&&vs.set(s.strings,t=new Pt(s)),t}k(s){Re(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,e,r=0;for(let i of s)r===t.length?t.push(e=new o(this.O(Dt()),this.O(Dt()),this,this.options)):e=t[r],e._$AI(i),r++;r<t.length&&(this._$AR(e&&e._$AB.nextSibling,r),t.length=r);}_$AR(s=this._$AA.nextSibling,t){for(this._$AP?.(false,true,t);s!==this._$AB;){let e=ds(s).nextSibling;ds(s).remove(),s=e;}}setConnected(s){this._$AM===void 0&&(this._$Cv=s,this._$AP?.(s));}},ht=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(s,t,e,r,i){this.type=1,this._$AH=p,this._$AN=void 0,this.element=s,this.name=t,this._$AM=r,this.options=i,e.length>2||e[0]!==""||e[1]!==""?(this._$AH=Array(e.length-1).fill(new String),this.strings=e):this._$AH=p;}_$AI(s,t=this,e,r){let i=this.strings,n=false;if(i===void 0)s=pt(this,s,t,0),n=!Ht(s)||s!==this._$AH&&s!==Y,n&&(this._$AH=s);else {let l=s,c,d;for(s=i[0],c=0;c<i.length-1;c++)d=pt(this,l[e+c],t,c),d===Y&&(d=this._$AH[c]),n||(n=!Ht(d)||d!==this._$AH[c]),d===p?s=p:s!==p&&(s+=(d??"")+i[c+1]),this._$AH[c]=d;}n&&!r&&this.j(s);}j(s){s===p?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,s??"");}},xe=class extends ht{constructor(){super(...arguments),this.type=3;}j(s){this.element[this.name]=s===p?void 0:s;}},Se=class extends ht{constructor(){super(...arguments),this.type=4;}j(s){this.element.toggleAttribute(this.name,!!s&&s!==p);}},Te=class extends ht{constructor(s,t,e,r,i){super(s,t,e,r,i),this.type=5;}_$AI(s,t=this){if((s=pt(this,s,t,0)??p)===Y)return;let e=this._$AH,r=s===p&&e!==p||s.capture!==e.capture||s.once!==e.once||s.passive!==e.passive,i=s!==p&&(e===p||r);r&&this.element.removeEventListener(this.name,this,e),i&&this.element.addEventListener(this.name,this,s),this._$AH=s;}handleEvent(s){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,s):this._$AH.handleEvent(s);}},we=class{constructor(s,t,e){this.element=s,this.type=6,this._$AN=void 0,this._$AM=t,this.options=e;}get _$AU(){return this._$AM._$AU}_$AI(s){pt(this,s);}};var qr=kt.litHtmlPolyfillSupport;qr?.(Pt,qt),(kt.litHtmlVersions??(kt.litHtmlVersions=[])).push("3.3.2");var _s=(o,s,t)=>{let e=t?.renderBefore??s,r=e._$litPart$;if(r===void 0){let i=t?.renderBefore??null;e._$litPart$=r=new qt(s.insertBefore(Dt(),i),i,void 0,t??{});}return r._$AI(o),r};var Ut=globalThis,E=class extends j{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){var t;let s=super.createRenderRoot();return (t=this.renderOptions).renderBefore??(t.renderBefore=s.firstChild),s}update(s){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(s),this._$Do=_s(t,this.renderRoot,this.renderOptions);}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(true);}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(false);}render(){return Y}};E._$litElement$=true,E.finalized=true,Ut.litElementHydrateSupport?.({LitElement:E});var Ur=Ut.litElementPolyfillSupport;Ur?.({LitElement:E});(Ut.litElementVersions??(Ut.litElementVersions=[])).push("4.2.2");var S=o=>(s,t)=>{t!==void 0?t.addInitializer(()=>{customElements.define(o,s);}):customElements.define(o,s);};var Fr={attribute:true,type:String,converter:Nt,reflect:false,hasChanged:te},Gr=(o=Fr,s,t)=>{let{kind:e,metadata:r}=t,i=globalThis.litPropertyMetadata.get(r);if(i===void 0&&globalThis.litPropertyMetadata.set(r,i=new Map),e==="setter"&&((o=Object.create(o)).wrapped=true),i.set(t.name,o),e==="accessor"){let{name:n}=t;return {set(l){let c=s.get.call(this);s.set.call(this,l),this.requestUpdate(n,c,o,true,l);},init(l){return l!==void 0&&this.C(n,void 0,o,l),l}}}if(e==="setter"){let{name:n}=t;return function(l){let c=this[n];s.call(this,l),this.requestUpdate(n,c,o,true,l);}}throw Error("Unsupported decorator location: "+e)};function L(o){return (s,t)=>typeof t=="object"?Gr(o,s,t):((e,r,i)=>{let n=r.hasOwnProperty(i);return r.constructor.createProperty(i,e),n?Object.getOwnPropertyDescriptor(r,i):void 0})(o,s,t)}function b(o){return L({...o,state:true,attribute:false})}var Ft=class extends E{constructor(){super(...arguments);this.method="";}createRenderRoot(){return this}render(){let t=this.method.toUpperCase();return a`<span class="method-badge method-badge-${t}">${t}</span>`}};u([L()],Ft.prototype,"method",2),Ft=u([S("bk-method-badge")],Ft);var P="/__brakit/api",F="/__brakit",w={flows:`${P}/flows`,requests:`${P}/requests`,events:`${P}/events`,clear:`${P}/clear`,fetches:`${P}/fetches`,errors:`${P}/errors`,logs:`${P}/logs`,queries:`${P}/queries`,metricsLive:`${P}/metrics/live`,insights:`${P}/insights`,tab:`${P}/tab`,activity:`${P}/activity`,graph:`${P}/graph`};var ut="polling",re="static",Br="auth-handshake",Wr="auth-check",Qr="middleware",Gt={[Br]:1,[Wr]:1,[Qr]:1};var ie="fetch";var oe="error_event",ne="query",ae="issues";var Ie={overview:"Overview",actions:"Actions",requests:"Requests",fetches:"Server Fetches",queries:"Queries",errors:"Errors",logs:"Logs",performance:"Performance",security:"Security",graph:"Graph"},Ce={overview:"Live summary of your application",actions:"User actions captured as sequences of HTTP requests",requests:"All HTTP requests proxied through brakit",fetches:"Outbound HTTP calls made by your server to external services",queries:"Database queries executed during request handling",errors:"Unhandled exceptions and errors thrown by your application",logs:"Console output from your application",performance:"Endpoint health and response time trends",security:"Security findings and recommendations",graph:"Runtime dependency graph of your application"};var Me=100,mt=300,ft=800,Ne=2e3,Oe=100,ke=50,De=500;var J="__all__",pe={SELECT:"var(--blue)",INSERT:"var(--green)",UPDATE:"var(--amber)",DELETE:"var(--red)",COUNT:"var(--text-muted)"},As={error:"var(--red)",warn:"var(--amber)",info:"var(--blue)",debug:"var(--text-muted)",log:"var(--text-dim)"},qe=["#2563eb","#7c3aed","#16a34a","#d97706","#dc2626","#0891b2","#ea580c","#c026d3","#059669","#db2777"],Bt={green:"#4ade80",amber:"#fbbf24",red:"#f87171"},gt=[{max:Me,label:"Fast",color:"var(--green)",bg:"rgba(22,163,74,0.08)",border:"rgba(22,163,74,0.2)"},{max:mt,label:"Good",color:"var(--green)",bg:"rgba(22,163,74,0.06)",border:"rgba(22,163,74,0.15)"},{max:ft,label:"OK",color:"var(--amber)",bg:"rgba(217,119,6,0.06)",border:"rgba(217,119,6,0.15)"},{max:Ne,label:"Slow",color:"var(--red)",bg:"rgba(220,38,38,0.06)",border:"rgba(220,38,38,0.15)"},{max:1/0,label:"Critical",color:"var(--red)",bg:"rgba(220,38,38,0.08)",border:"rgba(220,38,38,0.2)"}],Is="rgba(228,228,231,0.8)",Ue="rgba(113,113,122,0.7)",Cs="10px monospace",Fe="9px monospace";var Ls={top:16,right:16,bottom:28,left:52},Ms={fetch:"var(--blue)",log:"var(--text-muted)",error:"var(--red)",query:"var(--accent)"},Ns={fetch:"FETCH",log:"LOG",error:"ERROR",query:"QUERY"},Os=new Set(["cookie","set-cookie","authorization","proxy-authorization","x-api-key","x-auth-token"]),ks={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",408:"Timeout",409:"Conflict",422:"Unprocessable",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},Ds=new Set(["host","connection","accept-encoding"]),Z={critical:{icon:"\u2717",cls:"critical",sort:0},warning:{icon:"\u26A0",cls:"warning",sort:1},info:{icon:"\u2139",cls:"info",sort:2}};function _(o){return o<1e3?o+"ms":(o/1e3).toFixed(1)+"s"}function et(o){return !o||o===0?"":o<1024?o+"b":(o/1024).toFixed(1)+"kb"}function tt(o){return o?o.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;"):""}function bt(o){return o>=500?"status-pill-5xx":o>=400?"status-pill-4xx":o>=300?"status-pill-3xx":"status-pill-2xx"}function Hs(o){return ks[o]||(o>=500?"Server Error":o>=400?"Client Error":"OK")}function jr(o,s){if(Os.has(o.toLowerCase())){let t=String(s);return t.length<=8?"****":t.slice(0,4)+"..."+t.slice(-4)+" ("+t.length+" chars)"}return String(s)}function Et(o){return !o||Object.keys(o).length===0?'<span style="color:var(--text-muted)">No headers</span>':Object.entries(o).map(([s,t])=>'<span class="json-key">'+tt(s)+"</span>: "+tt(jr(s,t))).join(`
4
+ `)}function nt(o){if(!o)return '<span style="color:var(--text-muted)">No body</span>';try{let s=JSON.parse(o);return Yr(JSON.stringify(s,null,2))}catch{return tt(o)}}function Yr(o){return tt(o).replace(/("(?:[^"\\]|\\.)*")(\s*:)?|\b(true|false)\b|\bnull\b|(-?\d+\.?\d*(?:[eE][+-]?\d+)?)/g,(s,t,e,r,i)=>t?e?'<span class="json-key">'+t+"</span>"+e:'<span class="json-str">'+t+"</span>":r?'<span class="json-bool">'+s+"</span>":i?'<span class="json-num">'+s+"</span>":s==="null"?'<span class="json-null">null</span>':s)}var Wt=class extends E{constructor(){super(...arguments);this.code=0;}createRenderRoot(){return this}render(){let t=bt(this.code);return a`<span class="status-pill ${t}">${this.code}</span>`}};u([L({type:Number})],Wt.prototype,"code",2),Wt=u([S("bk-status-pill")],Wt);var Qt=class extends E{constructor(){super(...arguments);this.ms=0;}createRenderRoot(){return this}render(){return a`<span class="req-duration">${_(this.ms)}</span>`}};u([L({type:Number})],Qt.prototype,"ms",2),Qt=u([S("bk-duration-label")],Qt);var yt=class extends E{constructor(){super(...arguments);this.title="";this.subtitle="";}createRenderRoot(){return this}render(){return a`
5
5
  <div class="empty">
6
6
  <span class="empty-title">${this.title}</span>
7
7
  <span class="empty-sub">${this.subtitle}</span>
8
8
  </div>
9
- `}};u([y()],ot.prototype,"title",2),u([y()],ot.prototype,"subtitle",2),ot=u([g("bk-empty-state")],ot);var C=class extends f{constructor(){super(...arguments);this.message="";this.visible=false;}createRenderRoot(){return this}static show(t){let s=document.querySelector("bk-toast");s&&s.showMessage(t);}showMessage(t){this.hideTimer&&clearTimeout(this.hideTimer),this.message=t,this.visible=true,this.hideTimer=setTimeout(()=>{this.visible=false;},2e3);}render(){return a`<div class="toast ${this.visible?"show":""}">${this.message}</div>`}};u([_()],C.prototype,"message",2),u([_()],C.prototype,"visible",2),C=u([g("bk-toast")],C);var V=class extends f{constructor(){super(...arguments);this.text="";this.label="Copy";this.toastMessage="Copied";}createRenderRoot(){return this}async copy(t){t.stopPropagation();try{await navigator.clipboard.writeText(this.text),C.show(this.toastMessage);}catch{}}render(){return a`<button class="query-detail-copy" @click=${this.copy}>${this.label}</button>`}};u([y()],V.prototype,"text",2),u([y()],V.prototype,"label",2),u([y({attribute:"toast-message"})],V.prototype,"toastMessage",2),V=u([g("bk-copy-button")],V);var Y=class extends f{constructor(){super(...arguments);this.value="";this.label="";this.color="";}createRenderRoot(){return this}render(){return a`
9
+ `}};u([L()],yt.prototype,"title",2),u([L()],yt.prototype,"subtitle",2),yt=u([S("bk-empty-state")],yt);var D=class extends E{constructor(){super(...arguments);this.message="";this.visible=false;}createRenderRoot(){return this}static show(t){let e=document.querySelector("bk-toast");e&&e.showMessage(t);}showMessage(t){this.hideTimer&&clearTimeout(this.hideTimer),this.message=t,this.visible=true,this.hideTimer=setTimeout(()=>{this.visible=false;},2e3);}render(){return a`<div class="toast ${this.visible?"show":""}">${this.message}</div>`}};u([b()],D.prototype,"message",2),u([b()],D.prototype,"visible",2),D=u([S("bk-toast")],D);var at=class extends E{constructor(){super(...arguments);this.text="";this.label="Copy";this.toastMessage="Copied";}createRenderRoot(){return this}async copy(t){t.stopPropagation();try{await navigator.clipboard.writeText(this.text),D.show(this.toastMessage);}catch{}}render(){return a`<button class="query-detail-copy" @click=${this.copy}>${this.label}</button>`}};u([L()],at.prototype,"text",2),u([L()],at.prototype,"label",2),u([L({attribute:"toast-message"})],at.prototype,"toastMessage",2),at=u([S("bk-copy-button")],at);var lt=class extends E{constructor(){super(...arguments);this.value="";this.label="";this.color="";}createRenderRoot(){return this}render(){return a`
10
10
  <div class="fetch-stat">
11
11
  <span class="fetch-stat-value" style="color:${this.color}">${this.value}</span>
12
12
  <span class="fetch-stat-label">${this.label}</span>
13
13
  </div>
14
- `}};u([y()],Y.prototype,"value",2),u([y()],Y.prototype,"label",2),u([y()],Y.prototype,"color",2),Y=u([g("bk-stat-card")],Y);var F=class extends Event{constructor(e,t,s,r){super("context-request",{bubbles:true,composed:true}),this.context=e,this.contextTarget=t,this.callback=s,this.subscribe=r??false;}};var it=class{constructor(e,t,s,r){if(this.subscribe=false,this.provided=false,this.value=void 0,this.t=(o,n)=>{this.unsubscribe&&(this.unsubscribe!==n&&(this.provided=false,this.unsubscribe()),this.subscribe||this.unsubscribe()),this.value=o,this.host.requestUpdate(),this.provided&&!this.subscribe||(this.provided=true,this.callback&&this.callback(o,n)),this.unsubscribe=n;},this.host=e,t.context!==void 0){let o=t;this.context=o.context,this.callback=o.callback,this.subscribe=o.subscribe??false;}else this.context=t,this.callback=s,this.subscribe=r??false;this.host.addController(this);}hostConnected(){this.dispatchRequest();}hostDisconnected(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=void 0);}dispatchRequest(){this.host.dispatchEvent(new F(this.context,this.host,this.t,this.subscribe));}};var Bt=class{get value(){return this.o}set value(e){this.setValue(e);}setValue(e,t=false){let s=t||!Object.is(e,this.o);this.o=e,s&&this.updateObservers();}constructor(e){this.subscriptions=new Map,this.updateObservers=()=>{for(let[t,{disposer:s}]of this.subscriptions)t(this.o,s);},e!==void 0&&(this.value=e);}addCallback(e,t,s){if(!s)return void e(this.value);this.subscriptions.has(e)||this.subscriptions.set(e,{disposer:()=>{this.subscriptions.delete(e);},consumerHost:t});let{disposer:r}=this.subscriptions.get(e);e(this.value,r);}clearCallbacks(){this.subscriptions.clear();}};var ge=class extends Event{constructor(e,t){super("context-provider",{bubbles:true,composed:true}),this.context=e,this.contextTarget=t;}},nt=class extends Bt{constructor(e,t,s){super(t.context!==void 0?t.initialValue:s),this.onContextRequest=r=>{if(r.context!==this.context)return;let o=r.contextTarget??r.composedPath()[0];o!==this.host&&(r.stopPropagation(),this.addCallback(r.callback,o,r.subscribe));},this.onProviderRequest=r=>{if(r.context!==this.context||(r.contextTarget??r.composedPath()[0])===this.host)return;let o=new Set;for(let[n,{consumerHost:l}]of this.subscriptions)o.has(n)||(o.add(n),l.dispatchEvent(new F(this.context,l,n,true)));r.stopPropagation();},this.host=e,t.context!==void 0?this.context=t.context:this.context=t,this.attachListeners(),this.host.addController?.(this);}attachListeners(){this.host.addEventListener("context-request",this.onContextRequest),this.host.addEventListener("context-provider",this.onProviderRequest);}hostConnected(){this.host.dispatchEvent(new ge(this.context,this.host));}};function Ee({context:i}){return (e,t)=>{let s=new WeakMap;if(typeof t=="object")return {get(){return e.get.call(this)},set(r){return s.get(this).setValue(r),e.set.call(this,r)},init(r){return s.set(this,new nt(this,{context:i,initialValue:r})),r}};{e.constructor.addInitializer((n=>{s.set(n,new nt(n,{context:i}));}));let r=Object.getOwnPropertyDescriptor(e,t),o;if(r===void 0){let n=new WeakMap;o={get(){return n.get(this)},set(l){s.get(this).setValue(l),n.set(this,l);},configurable:true,enumerable:true};}else {let n=r.set;o={...r,set(l){s.get(this).setValue(l),n?.call(this,l);}};}return void Object.defineProperty(e,t,o)}}}function R({context:i,subscribe:e}){return (t,s)=>{typeof s=="object"?s.addInitializer((function(){new it(this,{context:i,callback:r=>{t.set.call(this,r);},subscribe:e});})):t.constructor.addInitializer((r=>{new it(r,{context:i,callback:o=>{r[s]=o;},subscribe:e});}));}}var x="dashboard-store",Gt=class extends EventTarget{constructor(){super(...arguments);this._state={flows:[],requests:[],fetches:[],errors:[],logs:[],queries:[],issues:[],metrics:[],viewMode:"simple",activeView:"overview"};}get state(){return this._state}setFlows(t){this._state={...this._state,flows:t},this.notify("flows");}setRequests(t){this._state={...this._state,requests:t},this.notify("requests");}setFetches(t){this._state={...this._state,fetches:t},this.notify("fetches");}setErrors(t){this._state={...this._state,errors:t},this.notify("errors");}setLogs(t){this._state={...this._state,logs:t},this.notify("logs");}setQueries(t){this._state={...this._state,queries:t},this.notify("queries");}setIssues(t){this._state={...this._state,issues:t},this.notify("issues");}setMetrics(t){this._state={...this._state,metrics:t},this.notify("metrics");}prependRequest(t){let s=[t,...this._state.requests.slice(0,999)];this._state={...this._state,requests:s},this.notify("requests");}prependFetch(t){this._state={...this._state,fetches:[t,...this._state.fetches]},this.notify("fetches");}prependError(t){this._state={...this._state,errors:[t,...this._state.errors]},this.notify("errors");}prependLog(t){this._state={...this._state,logs:[t,...this._state.logs]},this.notify("logs");}prependQuery(t){this._state={...this._state,queries:[t,...this._state.queries]},this.notify("queries");}setActiveView(t){this._state={...this._state,activeView:t},this.notify("activeView");}setViewMode(t){this._state={...this._state,viewMode:t},this.notify("viewMode");}clearAll(){this._state={...this._state,flows:[],requests:[],fetches:[],errors:[],logs:[],queries:[],issues:[],metrics:[]},this.notify("all");}notify(t){this.dispatchEvent(new CustomEvent("state-changed",{detail:t}));}};var at=class extends f{constructor(){super(...arguments);this.expandedIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleError(t){this.expandedIdx=this.expandedIdx===t?-1:t;}renderErrorRow(t,s){let r=new Date(t.timestamp).toLocaleTimeString(),o=this.expandedIdx===s;return a`
14
+ `}};u([L()],lt.prototype,"value",2),u([L()],lt.prototype,"label",2),u([L()],lt.prototype,"color",2),lt=u([S("bk-stat-card")],lt);var st=class extends Event{constructor(s,t,e,r){super("context-request",{bubbles:true,composed:true}),this.context=s,this.contextTarget=t,this.callback=e,this.subscribe=r??false;}};var _t=class{constructor(s,t,e,r){if(this.subscribe=false,this.provided=false,this.value=void 0,this.t=(i,n)=>{this.unsubscribe&&(this.unsubscribe!==n&&(this.provided=false,this.unsubscribe()),this.subscribe||this.unsubscribe()),this.value=i,this.host.requestUpdate(),this.provided&&!this.subscribe||(this.provided=true,this.callback&&this.callback(i,n)),this.unsubscribe=n;},this.host=s,t.context!==void 0){let i=t;this.context=i.context,this.callback=i.callback,this.subscribe=i.subscribe??false;}else this.context=t,this.callback=e,this.subscribe=r??false;this.host.addController(this);}hostConnected(){this.dispatchRequest();}hostDisconnected(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=void 0);}dispatchRequest(){this.host.dispatchEvent(new st(this.context,this.host,this.t,this.subscribe));}};var he=class{get value(){return this.o}set value(s){this.setValue(s);}setValue(s,t=false){let e=t||!Object.is(s,this.o);this.o=s,e&&this.updateObservers();}constructor(s){this.subscriptions=new Map,this.updateObservers=()=>{for(let[t,{disposer:e}]of this.subscriptions)t(this.o,e);},s!==void 0&&(this.value=s);}addCallback(s,t,e){if(!e)return void s(this.value);this.subscriptions.has(s)||this.subscriptions.set(s,{disposer:()=>{this.subscriptions.delete(s);},consumerHost:t});let{disposer:r}=this.subscriptions.get(s);s(this.value,r);}clearCallbacks(){this.subscriptions.clear();}};var Ge=class extends Event{constructor(s,t){super("context-provider",{bubbles:true,composed:true}),this.context=s,this.contextTarget=t;}},$t=class extends he{constructor(s,t,e){super(t.context!==void 0?t.initialValue:e),this.onContextRequest=r=>{if(r.context!==this.context)return;let i=r.contextTarget??r.composedPath()[0];i!==this.host&&(r.stopPropagation(),this.addCallback(r.callback,i,r.subscribe));},this.onProviderRequest=r=>{if(r.context!==this.context||(r.contextTarget??r.composedPath()[0])===this.host)return;let i=new Set;for(let[n,{consumerHost:l}]of this.subscriptions)i.has(n)||(i.add(n),l.dispatchEvent(new st(this.context,l,n,true)));r.stopPropagation();},this.host=s,t.context!==void 0?this.context=t.context:this.context=t,this.attachListeners(),this.host.addController?.(this);}attachListeners(){this.host.addEventListener("context-request",this.onContextRequest),this.host.addEventListener("context-provider",this.onProviderRequest);}hostConnected(){this.host.dispatchEvent(new Ge(this.context,this.host));}};function Be({context:o}){return (s,t)=>{let e=new WeakMap;if(typeof t=="object")return {get(){return s.get.call(this)},set(r){return e.get(this).setValue(r),s.set.call(this,r)},init(r){return e.set(this,new $t(this,{context:o,initialValue:r})),r}};{s.constructor.addInitializer((n=>{e.set(n,new $t(n,{context:o}));}));let r=Object.getOwnPropertyDescriptor(s,t),i;if(r===void 0){let n=new WeakMap;i={get(){return n.get(this)},set(l){e.get(this).setValue(l),n.set(this,l);},configurable:true,enumerable:true};}else {let n=r.set;i={...r,set(l){e.get(this).setValue(l),n?.call(this,l);}};}return void Object.defineProperty(s,t,i)}}}function I({context:o,subscribe:s}){return (t,e)=>{typeof e=="object"?e.addInitializer((function(){new _t(this,{context:o,callback:r=>{t.set.call(this,r);},subscribe:s});})):t.constructor.addInitializer((r=>{new _t(r,{context:o,callback:i=>{r[e]=i;},subscribe:s});}));}}var A="dashboard-store",ue=class extends EventTarget{constructor(){super(...arguments);this._state={flows:[],requests:[],fetches:[],errors:[],logs:[],queries:[],issues:[],metrics:[],viewMode:"simple",activeView:"overview"};}get state(){return this._state}setFlows(t){this._state={...this._state,flows:t},this.notify("flows");}setRequests(t){this._state={...this._state,requests:t},this.notify("requests");}setFetches(t){this._state={...this._state,fetches:t},this.notify("fetches");}setErrors(t){this._state={...this._state,errors:t},this.notify("errors");}setLogs(t){this._state={...this._state,logs:t},this.notify("logs");}setQueries(t){this._state={...this._state,queries:t},this.notify("queries");}setIssues(t){this._state={...this._state,issues:t},this.notify("issues");}setMetrics(t){this._state={...this._state,metrics:t},this.notify("metrics");}prependRequest(t){let e=[t,...this._state.requests.slice(0,999)];this._state={...this._state,requests:e},this.notify("requests");}prependFetch(t){let e=[t,...this._state.fetches.slice(0,999)];this._state={...this._state,fetches:e},this.notify("fetches");}prependError(t){let e=[t,...this._state.errors.slice(0,999)];this._state={...this._state,errors:e},this.notify("errors");}prependLog(t){let e=[t,...this._state.logs.slice(0,999)];this._state={...this._state,logs:e},this.notify("logs");}prependQuery(t){let e=[t,...this._state.queries.slice(0,999)];this._state={...this._state,queries:e},this.notify("queries");}setActiveView(t){this._state={...this._state,activeView:t},this.notify("activeView");}setViewMode(t){this._state={...this._state,viewMode:t},this.notify("viewMode");}clearAll(){this._state={...this._state,flows:[],requests:[],fetches:[],errors:[],logs:[],queries:[],issues:[],metrics:[]},this.notify("all");}notify(t){this.dispatchEvent(new CustomEvent("state-changed",{detail:t}));}};var xt=class extends E{constructor(){super(...arguments);this.expandedIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleError(t){this.expandedIdx=this.expandedIdx===t?-1:t;}renderErrorRow(t,e){let r=new Date(t.timestamp).toLocaleTimeString(),i=this.expandedIdx===e;return a`
15
15
  <div
16
- class="req-row tel-clickable ${o?"expanded":""}"
17
- @click=${()=>this.toggleError(s)}
16
+ class="req-row tel-clickable ${i?"expanded":""}"
17
+ @click=${()=>this.toggleError(e)}
18
18
  >
19
19
  <span class="tel-error-name" title=${t.name}>${t.name}</span>
20
20
  <span class="tel-message" title=${t.message}>${t.message}</span>
21
21
  <span class="tel-timestamp">${r}</span>
22
22
  </div>
23
- ${o&&t.stack?a`<div class="error-stack">${t.stack}</div>`:d}
23
+ ${i&&t.stack?a`<div class="error-stack">${t.stack}</div>`:p}
24
24
  `}render(){let t=this.store.state.errors;return t.length===0?a`<bk-empty-state
25
25
  title="No errors"
26
26
  subtitle="No errors have been captured yet"
@@ -31,54 +31,54 @@
31
31
  <span style="width:130px;text-align:right">Time</span>
32
32
  </div>
33
33
  <div id="error-list">
34
- ${t.map((s,r)=>this.renderErrorRow(s,r))}
34
+ ${t.map((e,r)=>this.renderErrorRow(e,r))}
35
35
  </div>
36
- `}};u([R({context:x})],at.prototype,"store",2),u([_()],at.prototype,"expandedIdx",2),at=u([g("bk-errors-view")],at);var wt=class extends f{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}renderAnalysis(e){if(e.length===0)return d;let t={error:0,warn:0,info:0,debug:0,log:0};for(let s of e)t[s.level]!==void 0&&t[s.level]++;return a`
36
+ `}};u([I({context:A})],xt.prototype,"store",2),u([b()],xt.prototype,"expandedIdx",2),xt=u([S("bk-errors-view")],xt);var jt=class extends E{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}renderAnalysis(s){if(s.length===0)return p;let t={error:0,warn:0,info:0,debug:0,log:0};for(let e of s)t[e.level]!==void 0&&t[e.level]++;return a`
37
37
  <div id="log-analysis">
38
38
  <div class="fetch-summary">
39
- <bk-stat-card value=${String(e.length)} label="Total Logs"></bk-stat-card>
40
- ${t.error>0?a`<bk-stat-card value=${String(t.error)} label="Errors" color="var(--red)"></bk-stat-card>`:d}
41
- ${t.warn>0?a`<bk-stat-card value=${String(t.warn)} label="Warnings" color="var(--amber)"></bk-stat-card>`:d}
39
+ <bk-stat-card value=${String(s.length)} label="Total Logs"></bk-stat-card>
40
+ ${t.error>0?a`<bk-stat-card value=${String(t.error)} label="Errors" color="var(--red)"></bk-stat-card>`:p}
41
+ ${t.warn>0?a`<bk-stat-card value=${String(t.warn)} label="Warnings" color="var(--amber)"></bk-stat-card>`:p}
42
42
  <bk-stat-card value=${String(t.info)} label="Info"></bk-stat-card>
43
- ${t.debug>0?a`<bk-stat-card value=${String(t.debug)} label="Debug"></bk-stat-card>`:d}
44
- ${t.log>0?a`<bk-stat-card value=${String(t.log)} label="Log"></bk-stat-card>`:d}
43
+ ${t.debug>0?a`<bk-stat-card value=${String(t.debug)} label="Debug"></bk-stat-card>`:p}
44
+ ${t.log>0?a`<bk-stat-card value=${String(t.log)} label="Log"></bk-stat-card>`:p}
45
45
  </div>
46
46
  </div>
47
- `}renderLogRow(e){let t=new Date(e.timestamp).toLocaleTimeString();return a`
47
+ `}renderLogRow(s){let t=new Date(s.timestamp).toLocaleTimeString();return a`
48
48
  <div class="req-row">
49
- <span class="tel-level tel-level-${e.level}">${e.level.toUpperCase()}</span>
50
- <span class="tel-message tel-mono" title=${e.message}>${e.message}</span>
49
+ <span class="tel-level tel-level-${s.level}">${s.level.toUpperCase()}</span>
50
+ <span class="tel-message tel-mono" title=${s.message}>${s.message}</span>
51
51
  <span class="tel-timestamp">${t}</span>
52
52
  </div>
53
- `}render(){let e=this.store.state.logs;return e.length===0?a`<bk-empty-state
53
+ `}render(){let s=this.store.state.logs;return s.length===0?a`<bk-empty-state
54
54
  title="No logs"
55
55
  subtitle="No console output has been captured yet"
56
56
  ></bk-empty-state>`:a`
57
- ${this.renderAnalysis(e)}
57
+ ${this.renderAnalysis(s)}
58
58
  <div class="col-header">
59
59
  <span style="width:52px">Level</span>
60
60
  <span style="flex:1">Message</span>
61
61
  <span style="width:130px;text-align:right">Time</span>
62
62
  </div>
63
63
  <div id="log-list">
64
- ${e.map(t=>this.renderLogRow(t))}
64
+ ${s.map(t=>this.renderLogRow(t))}
65
65
  </div>
66
- `}};u([R({context:x})],wt.prototype,"store",2),wt=u([g("bk-logs-view")],wt);var Xs=new Set(["SELECT","FROM","WHERE","AND","OR","INSERT","INTO","VALUES","UPDATE","SET","DELETE","JOIN","LEFT","RIGHT","INNER","OUTER","ON","GROUP","BY","ORDER","HAVING","LIMIT","OFFSET","AS","IN","NOT","NULL","IS","LIKE","BETWEEN","EXISTS","CASE","WHEN","THEN","ELSE","END","COUNT","SUM","AVG","MIN","MAX","DISTINCT","UNION","ALL","CREATE","TABLE","ALTER","DROP","INDEX","RETURNING","WITH","RECURSIVE","OVER","PARTITION","WINDOW","FETCH","NEXT","ROWS","ONLY","CAST","COALESCE","NULLIF","EXTRACT","INTERVAL","TRUE","FALSE","ASC","DESC","USING","NATURAL","CROSS","FULL","ROLLBACK","COMMIT","BEGIN","TRANSACTION","SAVEPOINT","RELEASE"]);function ns(i){let e=i.trim().match(/^(\w+)/);return e?e[1].toUpperCase():"?"}function as(i){let e=i.replace(/\s+/g," ").trim(),t=e.match(/\bFROM\s+["'`]?(\w+)["'`]?/i);if(t)return t[1];let s=e.match(/\bINTO\s+["'`]?(\w+)["'`]?/i);if(s)return s[1];let r=e.match(/\bUPDATE\s+["'`]?(\w+)["'`]?/i);return r?r[1]:""}function ls(i){return P(i).replace(/\b\w+\b/g,e=>Xs.has(e.toUpperCase())?'<span class="sql-kw">'+e+"</span>":e)}var lt=class extends f{constructor(){super(...arguments);this.expandedIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleQuery(t){this.expandedIdx=this.expandedIdx===t?-1:t;}queryDuration(t){return t===0?"<1ms":v(t)}getQueryInfo(t){let s=(t.normalizedOp||t.operation||(t.sql?ns(t.sql):"?")).toUpperCase(),r=t.table||t.model||(t.sql?as(t.sql):""),o=t.sql||s+" "+r;return {op:s,table:r,sqlText:o}}renderQueryRow(t,s){let{op:r,table:o,sqlText:n}=this.getQueryInfo(t),l=Ft[r]||"var(--text-dim)",c=t.durationMs>de,p=t.sql||r+" "+o,h=this.expandedIdx===s;return a`
66
+ `}};u([I({context:A})],jt.prototype,"store",2),jt=u([S("bk-logs-view")],jt);var Ps={CHILD:2},qs=o=>(...s)=>({_$litDirective$:o,values:s}),me=class{constructor(s){}get _$AU(){return this._$AM._$AU}_$AT(s,t,e){this._$Ct=s,this._$AM=t,this._$Ci=e;}_$AS(s,t){return this.update(s,t)}update(s,t){return this.render(...t)}};var Yt=class extends me{constructor(s){if(super(s),this.it=p,s.type!==Ps.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(s){if(s===p||s==null)return this._t=void 0,this.it=s;if(s===Y)return s;if(typeof s!="string")throw Error(this.constructor.directiveName+"() called with a non-string value");if(s===this.it)return this._t;this.it=s;let t=[s];return t.raw=t,this._t={_$litType$:this.constructor.resultType,strings:t,values:[]}}};Yt.directiveName="unsafeHTML",Yt.resultType=1;var U=qs(Yt);var Vr=new Set(["SELECT","FROM","WHERE","AND","OR","INSERT","INTO","VALUES","UPDATE","SET","DELETE","JOIN","LEFT","RIGHT","INNER","OUTER","ON","GROUP","BY","ORDER","HAVING","LIMIT","OFFSET","AS","IN","NOT","NULL","IS","LIKE","BETWEEN","EXISTS","CASE","WHEN","THEN","ELSE","END","COUNT","SUM","AVG","MIN","MAX","DISTINCT","UNION","ALL","CREATE","TABLE","ALTER","DROP","INDEX","RETURNING","WITH","RECURSIVE","OVER","PARTITION","WINDOW","FETCH","NEXT","ROWS","ONLY","CAST","COALESCE","NULLIF","EXTRACT","INTERVAL","TRUE","FALSE","ASC","DESC","USING","NATURAL","CROSS","FULL","ROLLBACK","COMMIT","BEGIN","TRANSACTION","SAVEPOINT","RELEASE"]);function Us(o){let s=o.trimStart().split(/\s/)[0];return s?s.toUpperCase():"?"}function Fs(o){let s=o.replace(/\s+/g," ").trim(),t=s.match(/\bFROM\s+["'`]?(\w+)["'`]?/i);if(t)return t[1];let e=s.match(/\bINTO\s+["'`]?(\w+)["'`]?/i);if(e)return e[1];let r=s.match(/\bUPDATE\s+["'`]?(\w+)["'`]?/i);return r?r[1]:""}function Gs(o){return tt(o).replace(/\b\w+\b/g,s=>Vr.has(s.toUpperCase())?'<span class="sql-kw">'+s+"</span>":s)}var St=class extends E{constructor(){super(...arguments);this.expandedIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleQuery(t){this.expandedIdx=this.expandedIdx===t?-1:t;}queryDuration(t){return t===0?"<1ms":_(t)}getQueryInfo(t){let e=(t.normalizedOp||t.operation||(t.sql?Us(t.sql):"?")).toUpperCase(),r=t.table||t.model||(t.sql?Fs(t.sql):""),i=t.sql||e+" "+r;return {op:e,table:r,sqlText:i}}renderQueryRow(t,e){let{op:r,table:i,sqlText:n}=this.getQueryInfo(t),l=pe[r]||"var(--text-dim)",c=t.durationMs>Oe,d=t.sql||r+" "+i,h=this.expandedIdx===e;return a`
67
67
  <div>
68
68
  <div
69
69
  class="req-row query-row tel-clickable ${h?"expanded":""}"
70
- @click=${()=>this.toggleQuery(s)}
70
+ @click=${()=>this.toggleQuery(e)}
71
71
  >
72
72
  <span class="query-op" title=${r} style="color:${l}">${r}</span>
73
- <span class="query-table" title=${o}>${o}</span>
74
- <span class="query-preview" title=${p}>${p}</span>
73
+ <span class="query-table" title=${i}>${i}</span>
74
+ <span class="query-preview" title=${d}>${d}</span>
75
75
  <span class="query-dur${c?" query-slow":""}">${this.queryDuration(t.durationMs)}</span>
76
76
  </div>
77
77
  <div class="query-detail ${h?"open":""}">
78
78
  ${h?a`
79
- <pre class="query-detail-sql" .innerHTML=${ls(n)}></pre>
79
+ <pre class="query-detail-sql">${U(Gs(n))}</pre>
80
80
  <bk-copy-button .text=${n} label="Copy"></bk-copy-button>
81
- `:d}
81
+ `:p}
82
82
  </div>
83
83
  </div>
84
84
  `}render(){let t=this.store.state.queries;return t.length===0?a`<bk-empty-state
@@ -92,37 +92,37 @@
92
92
  <span style="width:60px;text-align:right">Time</span>
93
93
  </div>
94
94
  <div id="query-list">
95
- ${t.map((s,r)=>this.renderQueryRow(s,r))}
95
+ ${t.map((e,r)=>this.renderQueryRow(e,r))}
96
96
  </div>
97
- `}};u([R({context:x})],lt.prototype,"store",2),u([_()],lt.prototype,"expandedIdx",2),lt=u([g("bk-queries-view")],lt);function be(i){return i.replace(/'/g,"'\\''")}function Ks(i,e){let t=Object.entries(i.headers||{}).filter(([o])=>!os.has(o)).map(([o,n])=>`-H '${be(o)}: ${be(n)}'`).join(" "),s=i.requestBody?` -d '${be(i.requestBody)}'`:"",r=e?`http://localhost:${e}`:"";return `curl -X ${i.method} ${t}${s} '${r}${i.url}'`}function ct(i){let e=window.__BRAKIT_CONFIG__?.port??"",t=Ks(i,e);navigator.clipboard.writeText(t).then(()=>C.show("Copied cURL command"));}var dt=class extends f{constructor(){super(...arguments);this.expandedId=null;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleRequest(t){this.expandedId=this.expandedId===t?null:t;}handleCopyAsCurl(t,s){s.stopPropagation(),ct(t);}renderDetail(t){return a`
97
+ `}};u([I({context:A})],St.prototype,"store",2),u([b()],St.prototype,"expandedIdx",2),St=u([S("bk-queries-view")],St);function We(o){return o.replaceAll("'","'\\''")}function Kr(o,s){let t=Object.entries(o.headers||{}).filter(([i])=>!Ds.has(i)).map(([i,n])=>`-H '${We(i)}: ${We(n)}'`).join(" "),e=o.requestBody?` -d '${We(o.requestBody)}'`:"",r=s?`http://localhost:${s}`:"";return `curl -X ${o.method} ${t}${e} '${r}${o.url}'`}function Tt(o){let s=window.__BRAKIT_CONFIG__?.port??"",t=Kr(o,s);navigator.clipboard.writeText(t).then(()=>D.show("Copied cURL command"));}var wt=class extends E{constructor(){super(...arguments);this.expandedId=null;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleRequest(t){this.expandedId=this.expandedId===t?null:t;}handleCopyAsCurl(t,e){e.stopPropagation(),Tt(t);}renderDetail(t){return a`
98
98
  <div class="detail-meta">
99
99
  <span><bk-method-badge .method=${t.method}></bk-method-badge> ${t.url}</span>
100
100
  <span><bk-status-pill .code=${t.statusCode}></bk-status-pill></span>
101
101
  <span>${t.durationMs}ms</span>
102
- ${t.responseSize?a`<span>${U(t.responseSize)}</span>`:d}
102
+ ${t.responseSize?a`<span>${et(t.responseSize)}</span>`:p}
103
103
  </div>
104
104
  <div class="request-timeline tl-hidden" data-request-id=${t.id} data-request-started=${String(t.startedAt)}></div>
105
105
  <div class="detail-grid">
106
- <div class="detail-section"><h4>Request Headers</h4><pre .innerHTML=${rt(t.headers)}></pre></div>
107
- <div class="detail-section"><h4>Response Headers</h4><pre .innerHTML=${rt(t.responseHeaders)}></pre></div>
108
- <div class="detail-section"><h4>Request Body</h4><pre .innerHTML=${Q(t.requestBody)}></pre></div>
109
- <div class="detail-section"><h4>Response Body</h4><pre .innerHTML=${Q(t.responseBody)}></pre></div>
106
+ <div class="detail-section"><h4>Request Headers</h4><pre>${U(Et(t.headers))}</pre></div>
107
+ <div class="detail-section"><h4>Response Headers</h4><pre>${U(Et(t.responseHeaders))}</pre></div>
108
+ <div class="detail-section"><h4>Request Body</h4><pre>${U(nt(t.requestBody))}</pre></div>
109
+ <div class="detail-section"><h4>Response Body</h4><pre>${U(nt(t.responseBody))}</pre></div>
110
110
  </div>
111
111
  <div class="detail-actions">
112
- <button class="btn btn-curl" @click=${s=>this.handleCopyAsCurl(t,s)}>Copy cURL</button>
112
+ <button class="btn btn-curl" @click=${e=>this.handleCopyAsCurl(t,e)}>Copy cURL</button>
113
113
  </div>
114
- `}renderRequestRow(t){let s=this.expandedId===t.id;return a`
115
- <div class="req-row ${s?"expanded":""}" @click=${()=>this.toggleRequest(t.id)}>
114
+ `}renderRequestRow(t){let e=this.expandedId===t.id;return a`
115
+ <div class="req-row ${e?"expanded":""}" @click=${()=>this.toggleRequest(t.id)}>
116
116
  <div class="req-summary">
117
117
  <bk-method-badge .method=${t.method}></bk-method-badge>
118
118
  <span class="req-url">${t.url}</span>
119
119
  <bk-status-pill .code=${t.statusCode}></bk-status-pill>
120
120
  <bk-duration-label .ms=${t.durationMs}></bk-duration-label>
121
- <span class="req-size">${U(t.responseSize)}</span>
121
+ <span class="req-size">${et(t.responseSize)}</span>
122
122
  </div>
123
123
  </div>
124
- <div class="req-detail ${s?"open":""}">${s?this.renderDetail(t):d}</div>
125
- `}render(){let t=this.store.state.requests.filter(s=>!s.path?.startsWith(N));return t.length===0?a`<bk-empty-state title="No requests" subtitle="No HTTP requests have been captured yet"></bk-empty-state>`:a`
124
+ <div class="req-detail ${e?"open":""}">${e?this.renderDetail(t):p}</div>
125
+ `}render(){let t=this.store.state.requests.filter(e=>!e.path?.startsWith(F));return t.length===0?a`<bk-empty-state title="No requests" subtitle="No HTTP requests have been captured yet"></bk-empty-state>`:a`
126
126
  <div class="col-header">
127
127
  <span style="width:60px">Method</span>
128
128
  <span style="flex:1">URL</span>
@@ -130,51 +130,51 @@
130
130
  <span style="width:70px;text-align:right">Time</span>
131
131
  <span style="width:60px;text-align:right">Size</span>
132
132
  </div>
133
- <div id="request-list">${t.map(s=>this.renderRequestRow(s))}</div>
134
- `}};u([R({context:x})],dt.prototype,"store",2),u([_()],dt.prototype,"expandedId",2),dt=u([g("bk-requests-view")],dt);var At=class extends f{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}buildGroups(e,t){let s=new Map;for(let o of t)s.set(o.id,o);let r={};for(let o of e){let n=o.method+" "+o.url;r[n]||(r[n]={method:o.method,url:o.url,count:0,totalDur:0,maxDur:0,errors:0,callers:{},statusCodes:{},firstTs:o.timestamp,lastTs:o.timestamp});let l=r[n];if(l.count++,l.totalDur+=o.durationMs,o.durationMs>l.maxDur&&(l.maxDur=o.durationMs),o.statusCode>=400&&l.errors++,l.statusCodes[o.statusCode]=(l.statusCodes[o.statusCode]||0)+1,o.timestamp<l.firstTs&&(l.firstTs=o.timestamp),o.timestamp>l.lastTs&&(l.lastTs=o.timestamp),o.parentRequestId){let c=s.get(o.parentRequestId);c&&(l.callers[c.method+" "+(c.path||c.url)]=1);}}return Object.values(r).sort((o,n)=>n.count-o.count)}renderSummary(e){let t=new Set,s=0,r=0;for(let n of e)t.add(n.url),n.statusCode>=400&&s++,r+=n.durationMs;let o=Math.round(r/e.length);return a`
133
+ <div id="request-list">${t.map(e=>this.renderRequestRow(e))}</div>
134
+ `}};u([I({context:A})],wt.prototype,"store",2),u([b()],wt.prototype,"expandedId",2),wt=u([S("bk-requests-view")],wt);var Xt=class extends E{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}buildGroups(s,t){let e=new Map;for(let i of t)e.set(i.id,i);let r={};for(let i of s){let n=i.method+" "+i.url;r[n]||(r[n]={method:i.method,url:i.url,count:0,totalDur:0,maxDur:0,errors:0,callers:{},statusCodes:{},firstTs:i.timestamp,lastTs:i.timestamp});let l=r[n];if(l.count++,l.totalDur+=i.durationMs,i.durationMs>l.maxDur&&(l.maxDur=i.durationMs),i.statusCode>=400&&l.errors++,l.statusCodes[i.statusCode]=(l.statusCodes[i.statusCode]||0)+1,i.timestamp<l.firstTs&&(l.firstTs=i.timestamp),i.timestamp>l.lastTs&&(l.lastTs=i.timestamp),i.parentRequestId){let c=e.get(i.parentRequestId);c&&(l.callers[c.method+" "+(c.path||c.url)]=1);}}return Object.values(r).sort((i,n)=>n.count-i.count)}renderSummary(s){let t=new Set,e=0,r=0;for(let n of s)t.add(n.url),n.statusCode>=400&&e++,r+=n.durationMs;let i=Math.round(r/s.length);return a`
135
135
  <div class="fetch-summary">
136
- <bk-stat-card value=${String(e.length)} label="Total Fetches"></bk-stat-card>
136
+ <bk-stat-card value=${String(s.length)} label="Total Fetches"></bk-stat-card>
137
137
  <bk-stat-card value=${String(t.size)} label="Unique URLs"></bk-stat-card>
138
- <bk-stat-card value=${String(s)} label="Errors" color=${s>0?"var(--red)":""}></bk-stat-card>
139
- <bk-stat-card value=${v(o)} label="Avg Duration"></bk-stat-card>
138
+ <bk-stat-card value=${String(e)} label="Errors" color=${e>0?"var(--red)":""}></bk-stat-card>
139
+ <bk-stat-card value=${_(i)} label="Avg Duration"></bk-stat-card>
140
140
  </div>
141
- `}formatTime(e){return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}renderGroup(e){let t=Math.round(e.totalDur/e.count),s=e.count>0?Math.round(e.errors/e.count*100):0,r=Object.keys(e.callers),o=Object.entries(e.statusCodes),n=o.length>0?Number(o.sort((l,c)=>c[1]-l[1])[0][0]):0;return a`
141
+ `}formatTime(s){return new Date(s).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}renderGroup(s){let t=Math.round(s.totalDur/s.count),e=s.count>0?Math.round(s.errors/s.count*100):0,r=Object.keys(s.callers),i=Object.entries(s.statusCodes),n=i.length>0?Number(i.sort((l,c)=>c[1]-l[1])[0][0]):0;return a`
142
142
  <div class="fetch-group">
143
143
  <div class="fetch-group-header">
144
- <bk-method-badge .method=${e.method}></bk-method-badge>
145
- <span class="fetch-group-url" title=${e.url}>${e.url}</span>
146
- ${n>0?a`<bk-status-pill .code=${n}></bk-status-pill>`:d}
147
- <span class="fetch-group-count">${e.count}x</span>
144
+ <bk-method-badge .method=${s.method}></bk-method-badge>
145
+ <span class="fetch-group-url" title=${s.url}>${s.url}</span>
146
+ ${n>0?a`<bk-status-pill .code=${n}></bk-status-pill>`:p}
147
+ <span class="fetch-group-count">${s.count}x</span>
148
148
  </div>
149
149
  <div class="fetch-group-meta">
150
- <span>avg ${v(t)}</span>
150
+ <span>avg ${_(t)}</span>
151
151
  <span class="fetch-group-sep">\u00b7</span>
152
- <span>max ${v(e.maxDur)}</span>
152
+ <span>max ${_(s.maxDur)}</span>
153
153
  <span class="fetch-group-sep">\u00b7</span>
154
- ${s>0?a`<span class="fetch-group-err">${s}% errors</span>`:a`<span class="fetch-group-ok">0% errors</span>`}
154
+ ${e>0?a`<span class="fetch-group-err">${e}% errors</span>`:a`<span class="fetch-group-ok">0% errors</span>`}
155
155
  </div>
156
- ${e.firstTs>0?a`
156
+ ${s.firstTs>0?a`
157
157
  <div class="fetch-group-timeline">
158
158
  <span class="fetch-group-timeline-dot"></span>
159
159
  <span class="fetch-group-timeline-range">
160
- ${this.formatTime(e.firstTs)}${e.firstTs!==e.lastTs?a` \u2192 ${this.formatTime(e.lastTs)}`:d}
160
+ ${this.formatTime(s.firstTs)}${s.firstTs!==s.lastTs?a` \u2192 ${this.formatTime(s.lastTs)}`:p}
161
161
  </span>
162
- </div>`:d}
162
+ </div>`:p}
163
163
  ${r.length>0?a`
164
164
  <div class="fetch-group-callers">
165
165
  <span class="fetch-group-callers-label">Called by</span>
166
166
  ${r.map(l=>a`<span class="fetch-group-caller-pill">${l}</span>`)}
167
- </div>`:d}
167
+ </div>`:p}
168
168
  </div>
169
- `}render(){let e=this.store.state.fetches,t=this.store.state.requests;if(e.length===0)return a`<bk-empty-state title="No fetches" subtitle="No outbound HTTP calls have been captured yet"></bk-empty-state>`;let s=this.buildGroups(e,t);return a`
169
+ `}render(){let s=this.store.state.fetches,t=this.store.state.requests;if(s.length===0)return a`<bk-empty-state title="No fetches" subtitle="No outbound HTTP calls have been captured yet"></bk-empty-state>`;let e=this.buildGroups(s,t);return a`
170
170
  <div class="fetch-analysis" id="fetch-analysis">
171
- ${this.renderSummary(e)}
172
- ${s.length>0?a`
173
- <div class="fetch-groups-title">Grouped by URL (${s.length})</div>
174
- <div class="fetch-groups">${s.map(r=>this.renderGroup(r))}</div>
175
- `:d}
171
+ ${this.renderSummary(s)}
172
+ ${e.length>0?a`
173
+ <div class="fetch-groups-title">Grouped by URL (${e.length})</div>
174
+ <div class="fetch-groups">${e.map(r=>this.renderGroup(r))}</div>
175
+ `:p}
176
176
  </div>
177
- `}};u([R({context:x})],At.prototype,"store",2),At=u([g("bk-fetches-view")],At);function cs(i,e){if(e>=400)return "var(--red)";switch(i){case "GET":return "var(--green)";case "POST":return "var(--blue)";case "PUT":case "PATCH":return "var(--amber)";case "DELETE":return "var(--red)";default:return "var(--text-muted)"}}function _e(i){return i==="query"?"var(--accent)":"var(--cyan)"}function tr(i){return i.type==="query"||i.type==="fetch"}function er(i){let e=(i.normalizedOp||i.operation||"QUERY").toUpperCase(),t=i.table||i.model||"";return {label:`${e} ${t}`,tooltip:i.sql||`${e} ${t}`}}function sr(i){return {label:`${i.method} ${i.url}`,tooltip:`${i.method} ${i.url}`}}function rr(i,e,t,s,r,o){let n=i.data.durationMs||0,l,c;if(o){let p=Math.max(i.timestamp-s,0);l=Math.min(p/r*100,95),c=Math.max(n/r*100,1.5);}else {let p=t[0].timestamp,m=t[t.length-1].timestamp-p;l=m>0?(i.timestamp-p)/m*85:e/Math.max(t.length-1,1)*85,c=Math.max(n/r*100,1.5);}return l+c>100&&(c=Math.max(100-l,1.5)),{leftPct:l,widthPct:c}}function or(i,e){let t=i.timeline.filter(tr);if(t.length===0)return [];let s=e.startedAt,r=e.durationMs||1,o=Math.abs(t[0].timestamp-s)<r*10;return t.map((n,l)=>{let c=n.data.durationMs||0,{leftPct:p,widthPct:h}=rr(n,l,t,s,r,o),m=n.type==="query"?er(n.data):sr(n.data);return {type:n.type,label:m.label,durMs:c,durLabel:v(c),tooltip:m.tooltip,leftPct:p,widthPct:h}})}function ps(i,e){let t=i.requests.filter(l=>!l.isStrictModeDupe);if(t.length===0)return {rows:[],totalMs:0};let s=Math.min(...t.map(l=>l.startedAt)),o=Math.max(...t.map(l=>l.startedAt+l.durationMs))-s;return o===0?{rows:[],totalMs:0}:{rows:t.map(l=>{let c=(l.startedAt-s)/o*100,p=Math.max(l.durationMs/o*100,.5),h=e?.activities?.[l.id],m=h?or(h,l):[];return {label:`${l.method} ${l.label}`,leftPct:c,widthPct:p,color:cs(l.method,l.statusCode),durMs:l.durationMs,durLabel:v(l.durationMs),tooltip:`${l.method} ${l.label} (${v(l.durationMs)})`,subEvents:m}}),totalMs:o}}function us(i){let e=i.requests,t=[],s=[],r=[],o=[],n=new Map;for(let p of e){let h=p.label,m=p.pollingDurationMs||p.durationMs;if(!$t[p.category||""]){if(p.isDuplicate){let E=n.get(h);E?(E.count++,E.wastedMs+=m):n.set(h,{name:h,count:2,wastedMs:m});continue}if(p.statusCode>=400){s.push(h+" ("+is(p.statusCode)+")");continue}p.responseSize>51200&&r.push("Large response: "+h+" returned "+U(p.responseSize)),t.push(h);}}for(let p of n.values())o.push(p);let l="";if(o.length>0){let p=o.map(m=>m.name).join(", "),h=o.reduce((m,E)=>m+E.wastedMs,0);l="Your app fetches "+p+" multiple times on this page. This wastes ~"+v(h)+". Try caching these calls, deduplicating with React Query/SWR, or moving them to a shared layout.";}else s.length>0&&(l="Some requests are failing. Check your API routes and make sure the endpoints exist.");let c=e.filter(p=>p.durationMs>2e3&&p.category!==J);return c.length>0&&!l&&(l=c.map(p=>p.label).join(", ")+` is taking over ${v(2e3)}. Consider adding caching or optimizing the backend query.`),{successes:t,errors:s,warnings:r,duplicates:o,tip:l}}var L=class extends f{constructor(){super(...arguments);this.expandedFlowIdx=-1;this.expandedSubReqIdx=-1;this.flowDetailTab="insights";this.flowTimeline=null;this.flowTimelineLoading=false;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}get flows(){return this.store.state.flows}get viewMode(){return this.store.state.viewMode}flowDotClass(t){return t.hasErrors?"dot-error":t.redundancyPct>0?"dot-warn":"dot-clean"}flowBadgeInfo(t){if(t.hasErrors){let s=t.requests.filter(r=>r.statusCode>=400).length;return {text:s+" error"+(s!==1?"s":""),cls:"badge-error"}}return t.redundancyPct>0?{text:t.redundancyPct+"% redundant",cls:"badge-warn"}:{text:"clean",cls:"badge-clean"}}toggleFlow(t){this.expandedFlowIdx===t?this.expandedFlowIdx=-1:(this.expandedFlowIdx=t,this.expandedSubReqIdx=-1,this.flowDetailTab="insights",this.flowTimeline=null);}toggleSubReq(t,s){s.stopPropagation(),this.expandedSubReqIdx=this.expandedSubReqIdx===t?-1:t;}toggleBodyBlock(t){t.stopPropagation();let s=t.currentTarget,r=s.parentElement;if(!r)return;s.classList.toggle("open");let o=r.querySelector("pre");o&&o.classList.toggle("open");}switchTab(t,s,r){r.stopPropagation(),this.flowDetailTab=t,t==="timeline"&&!this.flowTimeline&&this.loadFlowTimeline(s);}async loadFlowTimeline(t){if(this.flowTimelineLoading)return;let s=t.requests.map(r=>r.id).filter(Boolean);if(s.length!==0){this.flowTimelineLoading=true;try{let r=await fetch(`${$.activity}?requestIds=${s.join(",")}`);if(!r.ok){this.flowTimelineLoading=!1;return}this.flowTimeline=await r.json();}catch{}this.flowTimelineLoading=false;}}loadTimelineForContainer(t){let s=t.querySelectorAll(".request-timeline");for(let r of s){let o=r.getAttribute("data-request-id");if(o&&!r.hasAttribute("data-loaded")){r.setAttribute("data-loaded","1");let n=document.createElement("bk-timeline-panel");n.setAttribute("request-id",o),n.setAttribute("request-started",r.getAttribute("data-request-started")||"0"),r.appendChild(n),r.classList.remove("tl-hidden");}}}updated(){if(this.expandedFlowIdx>=0&&this.flowDetailTab==="insights"){let t=this.querySelector(".flow-expand.open");t&&this.loadTimelineForContainer(t);}}render(){let t=this.flows;return t.length===0?a`<bk-empty-state
177
+ `}};u([I({context:A})],Xt.prototype,"store",2),Xt=u([S("bk-fetches-view")],Xt);function Bs(o,s){if(s>=400)return "var(--red)";switch(o){case "GET":return "var(--green)";case "POST":return "var(--blue)";case "PUT":case "PATCH":return "var(--amber)";case "DELETE":return "var(--red)";default:return "var(--text-muted)"}}function Qe(o){return o==="query"?"var(--accent)":"var(--cyan)"}function ti(o){return o.type==="query"||o.type==="fetch"}function ei(o){let s=(o.normalizedOp||o.operation||"QUERY").toUpperCase(),t=o.table||o.model||"";return {label:`${s} ${t}`,tooltip:o.sql||`${s} ${t}`}}function si(o){return {label:`${o.method} ${o.url}`,tooltip:`${o.method} ${o.url}`}}function ri(o,s,t,e,r,i){let n=o.data.durationMs||0,l,c;if(i){let d=Math.max(o.timestamp-e,0);l=Math.min(d/r*100,95),c=Math.max(n/r*100,1.5);}else {let d=t[0].timestamp,m=t[t.length-1].timestamp-d;l=m>0?(o.timestamp-d)/m*85:s/Math.max(t.length-1,1)*85,c=Math.max(n/r*100,1.5);}return l+c>100&&(c=Math.max(100-l,1.5)),{leftPct:l,widthPct:c}}function ii(o,s){let t=o.timeline.filter(ti);if(t.length===0)return [];let e=s.startedAt,r=s.durationMs||1,i=Math.abs(t[0].timestamp-e)<r*10;return t.map((n,l)=>{let c=n.data.durationMs||0,{leftPct:d,widthPct:h}=ri(n,l,t,e,r,i),m=n.type==="query"?ei(n.data):si(n.data);return {type:n.type,label:m.label,durMs:c,durLabel:_(c),tooltip:m.tooltip,leftPct:d,widthPct:h}})}function Qs(o,s){let t=o.requests.filter(l=>!l.isStrictModeDupe);if(t.length===0)return {rows:[],totalMs:0};let e=Math.min(...t.map(l=>l.startedAt)),i=Math.max(...t.map(l=>l.startedAt+l.durationMs))-e;return i===0?{rows:[],totalMs:0}:{rows:t.map(l=>{let c=(l.startedAt-e)/i*100,d=Math.max(l.durationMs/i*100,.5),h=s?.activities?.[l.id],m=h?ii(h,l):[];return {label:`${l.method} ${l.label}`,leftPct:c,widthPct:d,color:Bs(l.method,l.statusCode),durMs:l.durationMs,durLabel:_(l.durationMs),tooltip:`${l.method} ${l.label} (${_(l.durationMs)})`,subEvents:m}}),totalMs:i}}function js(o){let s=o.requests,t=[],e=[],r=[],i=[],n=new Map;for(let d of s){let h=d.label,m=d.pollingDurationMs||d.durationMs;if(!Gt[d.category||""]){if(d.isDuplicate){let v=n.get(h);v?(v.count++,v.wastedMs+=m):n.set(h,{name:h,count:2,wastedMs:m});continue}if(d.statusCode>=400){e.push(h+" ("+Hs(d.statusCode)+")");continue}d.responseSize>51200&&r.push("Large response: "+h+" returned "+et(d.responseSize)),t.push(h);}}for(let d of n.values())i.push(d);let l="";if(i.length>0){let d=i.map(m=>m.name).join(", "),h=i.reduce((m,v)=>m+v.wastedMs,0);l="Your app fetches "+d+" multiple times on this page. This wastes ~"+_(h)+". Try caching these calls, deduplicating with React Query/SWR, or moving them to a shared layout.";}else e.length>0&&(l="Some requests are failing. Check your API routes and make sure the endpoints exist.");let c=s.filter(d=>d.durationMs>2e3&&d.category!==ut);return c.length>0&&!l&&(l=c.map(d=>d.label).join(", ")+` is taking over ${_(2e3)}. Consider adding caching or optimizing the backend query.`),{successes:t,errors:e,warnings:r,duplicates:i,tip:l}}var W=class extends E{constructor(){super(...arguments);this.expandedFlowIdx=-1;this.expandedSubReqIdx=-1;this.flowDetailTab="insights";this.flowTimeline=null;this.flowTimelineLoading=false;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}get flows(){return this.store.state.flows}get viewMode(){return this.store.state.viewMode}flowDotClass(t){return t.hasErrors?"dot-error":t.redundancyPct>0?"dot-warn":"dot-clean"}flowBadgeInfo(t){if(t.hasErrors){let e=t.requests.filter(r=>r.statusCode>=400).length;return {text:e+" error"+(e!==1?"s":""),cls:"badge-error"}}return t.redundancyPct>0?{text:t.redundancyPct+"% redundant",cls:"badge-warn"}:{text:"clean",cls:"badge-clean"}}toggleFlow(t){this.expandedFlowIdx===t?this.expandedFlowIdx=-1:(this.expandedFlowIdx=t,this.expandedSubReqIdx=-1,this.flowDetailTab="insights",this.flowTimeline=null);}toggleSubReq(t,e){e.stopPropagation(),this.expandedSubReqIdx=this.expandedSubReqIdx===t?-1:t;}toggleBodyBlock(t){t.stopPropagation();let e=t.currentTarget,r=e.parentElement;if(!r)return;e.classList.toggle("open");let i=r.querySelector("pre");i&&i.classList.toggle("open");}switchTab(t,e,r){r.stopPropagation(),this.flowDetailTab=t,t==="timeline"&&!this.flowTimeline&&this.loadFlowTimeline(e);}async loadFlowTimeline(t){if(this.flowTimelineLoading)return;let e=t.requests.map(r=>r.id).filter(Boolean);if(e.length!==0){this.flowTimelineLoading=true;try{let r=await fetch(`${w.activity}?requestIds=${e.join(",")}`);if(!r.ok){this.flowTimelineLoading=!1;return}this.flowTimeline=await r.json();}catch{}this.flowTimelineLoading=false;}}loadTimelineForContainer(t){let e=t.querySelectorAll(".request-timeline");for(let r of e){let i=r.getAttribute("data-request-id");if(i&&!r.hasAttribute("data-loaded")){r.setAttribute("data-loaded","1");let n=document.createElement("bk-timeline-panel");n.setAttribute("request-id",i),n.setAttribute("request-started",r.getAttribute("data-request-started")||"0"),r.appendChild(n),r.classList.remove("tl-hidden");}}}updated(){if(this.expandedFlowIdx>=0&&this.flowDetailTab==="insights"){let t=this.querySelector(".flow-expand.open");t&&this.loadTimelineForContainer(t);}}render(){let t=this.flows;return t.length===0?a`<bk-empty-state
178
178
  title="No actions yet"
179
179
  subtitle="Start using your app to see user action flows here"
180
180
  ></bk-empty-state>`:a`
@@ -186,15 +186,15 @@
186
186
  <span style="width:70px;text-align:right">Time</span>
187
187
  </div>
188
188
  <div id="flow-list">
189
- ${t.map((s,r)=>this.renderFlowRow(s,r))}
189
+ ${t.map((e,r)=>this.renderFlowRow(e,r))}
190
190
  </div>
191
- `}renderFlowRow(t,s){let r=this.expandedFlowIdx===s,o=this.flowDotClass(t),n=this.flowBadgeInfo(t);return a`
191
+ `}renderFlowRow(t,e){let r=this.expandedFlowIdx===e,i=this.flowDotClass(t),n=this.flowBadgeInfo(t);return a`
192
192
  <div
193
193
  class="flow-row ${r?"expanded":""}"
194
- @click=${()=>this.toggleFlow(s)}
194
+ @click=${()=>this.toggleFlow(e)}
195
195
  >
196
196
  <div class="flow-summary-row">
197
- <span class="flow-status-dot ${o}"></span>
197
+ <span class="flow-status-dot ${i}"></span>
198
198
  <span class="flow-label">${t.label}</span>
199
199
  <span class="flow-req-count"
200
200
  >${t.requests.length}
@@ -202,20 +202,20 @@
202
202
  >
203
203
  <span class="flow-badge-pill ${n.cls}">${n.text}</span>
204
204
  <span class="flow-duration"
205
- >${v(t.totalDurationMs)}</span
205
+ >${_(t.totalDurationMs)}</span
206
206
  >
207
207
  </div>
208
208
  </div>
209
209
  <div class="flow-expand ${r?"open":""}">
210
- ${r?this.renderFlowDetail(t):d}
210
+ ${r?this.renderFlowDetail(t):p}
211
211
  </div>
212
- `}renderFlowDetail(t){let s=this.viewMode==="simple"?"Insights":"Details";return a`
212
+ `}renderFlowDetail(t){let e=this.viewMode==="simple"?"Insights":"Details";return a`
213
213
  <div class="flow-detail-tabs">
214
214
  <button
215
215
  class="flow-tab ${this.flowDetailTab==="insights"?"active":""}"
216
216
  @click=${r=>this.switchTab("insights",t,r)}
217
217
  >
218
- ${s}
218
+ ${e}
219
219
  </button>
220
220
  <button
221
221
  class="flow-tab ${this.flowDetailTab==="timeline"?"active":""}"
@@ -225,13 +225,13 @@
225
225
  </button>
226
226
  </div>
227
227
  ${this.flowDetailTab==="insights"?this.viewMode==="simple"?this.renderFlowInsights(t):this.renderFlowSubReqs(t):this.renderFlowWaterfall(t)}
228
- `}renderFlowWaterfall(t){if(this.flowTimelineLoading)return a`<div class="wf-loading">Loading timeline...</div>`;let{rows:s,totalMs:r}=ps(t,this.flowTimeline);if(s.length===0)return d;let o=[];for(let n=0;n<=5;n++)o.push(v(r/5*n));return a`
228
+ `}renderFlowWaterfall(t){if(this.flowTimelineLoading)return a`<div class="wf-loading">Loading timeline...</div>`;let{rows:e,totalMs:r}=Qs(t,this.flowTimeline);if(e.length===0)return p;let i=[];for(let n=0;n<=5;n++)i.push(_(r/5*n));return a`
229
229
  <div class="flow-waterfall">
230
230
  <div class="wf-time-axis">
231
- ${o.map(n=>a`<span>${n}</span>`)}
231
+ ${i.map(n=>a`<span>${n}</span>`)}
232
232
  </div>
233
233
  <div class="wf-rows">
234
- ${s.map(n=>this.renderWaterfallGroup(n))}
234
+ ${e.map(n=>this.renderWaterfallGroup(n))}
235
235
  </div>
236
236
  </div>
237
237
  `}renderWaterfallGroup(t){return a`
@@ -246,109 +246,109 @@
246
246
  </div>
247
247
  <div class="wf-req-dur">${t.durLabel}</div>
248
248
  </div>
249
- ${t.subEvents.length>0?t.subEvents.map(s=>a`
250
- <div class="wf-sub-row" title="${s.tooltip}">
249
+ ${t.subEvents.length>0?t.subEvents.map(e=>a`
250
+ <div class="wf-sub-row" title="${e.tooltip}">
251
251
  <div class="wf-sub-label">
252
252
  <span
253
253
  class="wf-sub-dot"
254
- style="background:${_e(s.type)}"
254
+ style="background:${Qe(e.type)}"
255
255
  ></span>
256
- ${s.label}
256
+ ${e.label}
257
257
  </div>
258
258
  <div class="wf-bar-track">
259
259
  <div
260
260
  class="wf-bar wf-sub-bar-sized"
261
- style="left:${t.leftPct+s.leftPct/100*t.widthPct}%;width:${s.widthPct/100*t.widthPct}%;background:${_e(s.type)}"
261
+ style="left:${t.leftPct+e.leftPct/100*t.widthPct}%;width:${e.widthPct/100*t.widthPct}%;background:${Qe(e.type)}"
262
262
  ></div>
263
263
  </div>
264
- <div class="wf-sub-dur">${s.durLabel}</div>
264
+ <div class="wf-sub-dur">${e.durLabel}</div>
265
265
  </div>
266
- `):d}
266
+ `):p}
267
267
  </div>
268
- `}renderFlowInsights(t){let s=us(t),r=s.errors.length>0||s.duplicates.length>0||s.warnings.length>0||!!s.tip;return a`
268
+ `}renderFlowInsights(t){let e=js(t),r=e.errors.length>0||e.duplicates.length>0||e.warnings.length>0||!!e.tip;return a`
269
269
  <div>
270
270
  <div class="flow-traffic">
271
- ${t.requests.map(o=>this.renderTrafficCard(o))}
271
+ ${t.requests.map(i=>this.renderTrafficCard(i))}
272
272
  </div>
273
273
  ${r?a`
274
274
  <div class="flow-divider"></div>
275
275
  <div class="flow-insights">
276
- ${s.errors.map(o=>a`<div class="insight-line insight-error">
277
- ✗ ${o}
276
+ ${e.errors.map(i=>a`<div class="insight-line insight-error">
277
+ ✗ ${i}
278
278
  </div>`)}
279
- ${s.duplicates.map(o=>a`<div class="insight-line insight-warn">
280
- ⚠ ${o.name} — loaded ${o.count}x (wasting
281
- ~${v(o.wastedMs)})
279
+ ${e.duplicates.map(i=>a`<div class="insight-line insight-warn">
280
+ ⚠ ${i.name} — loaded ${i.count}x (wasting
281
+ ~${_(i.wastedMs)})
282
282
  </div>`)}
283
- ${s.warnings.map(o=>a`<div class="insight-line insight-warn">⚠ ${o}</div>`)}
284
- ${s.tip?a`<div class="insight-line insight-tip">
285
- Tip: ${s.tip}
286
- </div>`:d}
283
+ ${e.warnings.map(i=>a`<div class="insight-line insight-warn">⚠ ${i}</div>`)}
284
+ ${e.tip?a`<div class="insight-line insight-tip">
285
+ Tip: ${e.tip}
286
+ </div>`:p}
287
287
  </div>
288
- `:d}
288
+ `:p}
289
289
  </div>
290
- `}renderTrafficCard(t){if($t[t.category||""])return d;let s=st(t.statusCode),r=v(t.pollingDurationMs||t.durationMs),o=!t.isDuplicate&&t.category!==Ht&&t.category!==J||t.requestBody&&t.method!=="GET"||!!t.responseBody;return a`
290
+ `}renderTrafficCard(t){if(Gt[t.category||""])return p;let e=bt(t.statusCode),r=_(t.pollingDurationMs||t.durationMs),i=!t.isDuplicate&&t.category!==re&&t.category!==ut||t.requestBody&&t.method!=="GET"||!!t.responseBody;return a`
291
291
  <div
292
292
  class="traffic-card ${t.isStrictModeDupe?"strict-mode-dupe":""}"
293
293
  >
294
- <div class="traffic-card-header ${o?"has-details":""}">
294
+ <div class="traffic-card-header ${i?"has-details":""}">
295
295
  <bk-method-badge .method=${t.method}></bk-method-badge>
296
296
  <span class="traffic-card-path ${t.isDuplicate?"is-dup":""}"
297
297
  >${t.label}</span
298
298
  >
299
- <span class="status-pill ${s}">${t.statusCode}</span>
299
+ <span class="status-pill ${e}">${t.statusCode}</span>
300
300
  <span class="traffic-card-dur">${r}</span>
301
301
  ${t.isDuplicate?a`<span class="traffic-card-dup">duplicate</span>`:a`<span class="traffic-card-size"
302
- >${U(t.responseSize)}</span
302
+ >${et(t.responseSize)}</span
303
303
  >`}
304
304
  </div>
305
305
  ${t.isStrictModeDupe?a`<div class="strict-mode-banner">
306
306
  React Strict Mode duplicate — does not happen in production
307
- </div>`:d}
308
- ${!t.isDuplicate&&t.category!==Ht&&t.category!==J?a`<div
307
+ </div>`:p}
308
+ ${!t.isDuplicate&&t.category!==re&&t.category!==ut?a`<div
309
309
  class="request-timeline tl-hidden"
310
310
  data-request-id=${t.id}
311
311
  data-request-started=${String(t.startedAt)}
312
- ></div>`:d}
313
- ${t.requestBody&&t.method!=="GET"?this.renderBodyToggle("out","Request Body",t.requestBody):d}
314
- ${t.responseBody?this.renderBodyToggle("in","Response Body",t.responseBody):d}
312
+ ></div>`:p}
313
+ ${t.requestBody&&t.method!=="GET"?this.renderBodyToggle("out","Request Body",t.requestBody):p}
314
+ ${t.responseBody?this.renderBodyToggle("in","Response Body",t.responseBody):p}
315
315
  </div>
316
- `}renderBodyToggle(t,s,r){let o=t==="out"?"\u2192":"\u2190";return a`
316
+ `}renderBodyToggle(t,e,r){let i=t==="out"?"\u2192":"\u2190";return a`
317
317
  <div class="traffic-body">
318
318
  <button class="traffic-body-toggle" @click=${this.toggleBodyBlock}>
319
319
  <span class="chevron">▸</span
320
- ><span class="arrow-${t}">${o}</span> ${s}
320
+ ><span class="arrow-${t}">${i}</span> ${e}
321
321
  </button>
322
- <pre .innerHTML=${Q(r)}></pre>
322
+ <pre>${U(nt(r))}</pre>
323
323
  </div>
324
324
  `}renderFlowSubReqs(t){return a`<div class="flow-subreqs">
325
- ${t.requests.map((s,r)=>this.renderSubReqRow(s,r))}
326
- </div>`}renderSubReqRow(t,s){let r=this.expandedSubReqIdx===s,o=st(t.statusCode),n=t.pollingDurationMs?v(t.pollingDurationMs):v(t.durationMs);return a`
325
+ ${t.requests.map((e,r)=>this.renderSubReqRow(e,r))}
326
+ </div>`}renderSubReqRow(t,e){let r=this.expandedSubReqIdx===e,i=bt(t.statusCode),n=t.pollingDurationMs?_(t.pollingDurationMs):_(t.durationMs);return a`
327
327
  <div
328
328
  class="flow-subreq ${r?"expanded":""}"
329
- @click=${l=>this.toggleSubReq(s,l)}
329
+ @click=${l=>this.toggleSubReq(e,l)}
330
330
  >
331
331
  <bk-method-badge .method=${t.method}></bk-method-badge>
332
332
  <span class="subreq-label ${t.isDuplicate?"is-dup":""}"
333
333
  >${t.path||t.url}</span
334
334
  >
335
- ${t.isDuplicate?a`<span class="subreq-dup-tag">duplicate</span>`:d}
336
- <span class="status-pill ${o}">${t.statusCode}</span>
335
+ ${t.isDuplicate?a`<span class="subreq-dup-tag">duplicate</span>`:p}
336
+ <span class="status-pill ${i}">${t.statusCode}</span>
337
337
  <span class="subreq-dur">${n}</span>
338
338
  </div>
339
339
  <div class="flow-subreq-detail ${r?"open":""}">
340
- ${r?this.renderSubReqDetail(t):d}
340
+ ${r?this.renderSubReqDetail(t):p}
341
341
  </div>
342
- `}renderSubReqDetail(t){let s=st(t.statusCode);return a`
342
+ `}renderSubReqDetail(t){let e=bt(t.statusCode);return a`
343
343
  <div class="detail-meta">
344
344
  <span
345
- ><bk-method-badge .method=${t.method}></bk-method-badge> ${P(t.url)}</span
345
+ ><bk-method-badge .method=${t.method}></bk-method-badge> ${tt(t.url)}</span
346
346
  >
347
347
  <span
348
- ><span class="status-pill ${s}">${t.statusCode}</span></span
348
+ ><span class="status-pill ${e}">${t.statusCode}</span></span
349
349
  >
350
350
  <span>${t.durationMs}ms</span>
351
- ${t.responseSize?a`<span>${U(t.responseSize)}</span>`:d}
351
+ ${t.responseSize?a`<span>${et(t.responseSize)}</span>`:p}
352
352
  </div>
353
353
  <div
354
354
  class="request-timeline tl-hidden"
@@ -358,30 +358,30 @@
358
358
  <div class="detail-grid">
359
359
  <div class="detail-section">
360
360
  <h4>Request Headers</h4>
361
- <pre .innerHTML=${rt(t.headers)}></pre>
361
+ <pre>${U(Et(t.headers))}</pre>
362
362
  </div>
363
363
  <div class="detail-section">
364
364
  <h4>Response Headers</h4>
365
- <pre .innerHTML=${rt(t.responseHeaders)}></pre>
365
+ <pre>${U(Et(t.responseHeaders))}</pre>
366
366
  </div>
367
367
  <div class="detail-section">
368
368
  <h4>Request Body</h4>
369
- <pre .innerHTML=${Q(t.requestBody)}></pre>
369
+ <pre>${U(nt(t.requestBody))}</pre>
370
370
  </div>
371
371
  <div class="detail-section">
372
372
  <h4>Response Body</h4>
373
- <pre .innerHTML=${Q(t.responseBody)}></pre>
373
+ <pre>${U(nt(t.responseBody))}</pre>
374
374
  </div>
375
375
  </div>
376
376
  <div class="detail-actions">
377
377
  <button
378
378
  class="btn btn-curl"
379
- @click=${r=>{r.stopPropagation(),ct(t);}}
379
+ @click=${r=>{r.stopPropagation(),Tt(t);}}
380
380
  >
381
381
  Copy cURL
382
382
  </button>
383
383
  </div>
384
- `}};u([R({context:x})],L.prototype,"store",2),u([_()],L.prototype,"expandedFlowIdx",2),u([_()],L.prototype,"expandedSubReqIdx",2),u([_()],L.prototype,"flowDetailTab",2),u([_()],L.prototype,"flowTimeline",2),u([_()],L.prototype,"flowTimelineLoading",2),L=u([g("bk-flows-view")],L);var Ct=class extends f{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}render(){let e=(this.store.state.issues||[]).slice(),t=e.filter(l=>l.state==="open"||l.state==="fixing"||l.state==="regressed"),s=e.filter(l=>l.state==="resolved");if(t.length===0&&s.length===0)return this.store.state.requests.length>0||this.store.state.logs.length>0||this.store.state.queries.length>0?a`
384
+ `}};u([I({context:A})],W.prototype,"store",2),u([b()],W.prototype,"expandedFlowIdx",2),u([b()],W.prototype,"expandedSubReqIdx",2),u([b()],W.prototype,"flowDetailTab",2),u([b()],W.prototype,"flowTimeline",2),u([b()],W.prototype,"flowTimelineLoading",2),W=u([S("bk-flows-view")],W);var Vt=class extends E{createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}render(){let s=(this.store.state.issues||[]).slice(),t=s.filter(l=>l.state==="open"||l.state==="fixing"||l.state==="regressed"),e=s.filter(l=>l.state==="resolved");if(t.length===0&&e.length===0)return this.store.state.requests.length>0||this.store.state.logs.length>0||this.store.state.queries.length>0?a`
385
385
  <div class="sec-clear">
386
386
  <span class="sec-clear-icon">\u2713</span>
387
387
  <div class="sec-clear-text">
@@ -389,109 +389,109 @@
389
389
  <div class="sec-clear-sub">No security or quality issues detected this session</div>
390
390
  </div>
391
391
  </div>
392
- `:a`<bk-empty-state title="Waiting for requests..." subtitle="Start using your app to see security findings here"></bk-empty-state>`;let r=0,o=0,n=0;for(let l of t){let c=l.issue.severity;c==="critical"?r++:c==="info"?n++:o++;}return a`
392
+ `:a`<bk-empty-state title="Waiting for requests..." subtitle="Start using your app to see security findings here"></bk-empty-state>`;let r=0,i=0,n=0;for(let l of t){let c=l.issue.severity;c==="critical"?r++:c==="info"?n++:i++;}return a`
393
393
  <div id="security-content">
394
- ${this.renderSummary(t.length,s.length,r,o,n)}
395
- ${t.length===0&&s.length>0?a`
394
+ ${this.renderSummary(t.length,e.length,r,i,n)}
395
+ ${t.length===0&&e.length>0?a`
396
396
  <div class="sec-clear">
397
397
  <span class="sec-clear-icon">\u2713</span>
398
398
  <div class="sec-clear-text">
399
399
  <div class="sec-clear-title">All issues resolved</div>
400
- <div class="sec-clear-sub">${s.length} finding${s.length!==1?"s were":" was"} detected and fixed</div>
400
+ <div class="sec-clear-sub">${e.length} finding${e.length!==1?"s were":" was"} detected and fixed</div>
401
401
  </div>
402
402
  </div>
403
- `:d}
404
- ${t.length>0?this.renderOpenGroups(t):d}
405
- ${s.length>0?this.renderResolved(s):d}
403
+ `:p}
404
+ ${t.length>0?this.renderOpenGroups(t):p}
405
+ ${e.length>0?this.renderResolved(e):p}
406
406
  </div>
407
- `}renderSummary(e,t,s,r,o){return a`
407
+ `}renderSummary(s,t,e,r,i){return a`
408
408
  <div class="sec-summary">
409
409
  <div class="sec-summary-left">
410
- <span class="sec-summary-count">${e}</span>
411
- <span class="sec-summary-label">open issue${e!==1?"s":""}</span>
412
- ${t>0?a`<span class="sec-resolved-badge">${t} resolved</span>`:d}
410
+ <span class="sec-summary-count">${s}</span>
411
+ <span class="sec-summary-label">open issue${s!==1?"s":""}</span>
412
+ ${t>0?a`<span class="sec-resolved-badge">${t} resolved</span>`:p}
413
413
  </div>
414
414
  <div class="sec-summary-right">
415
- ${s>0?a`<span class="sec-badge critical">${s} critical</span>`:d}
416
- ${r>0?a`<span class="sec-badge warning">${r} warning</span>`:d}
417
- ${o>0?a`<span class="sec-badge info">${o} info</span>`:d}
415
+ ${e>0?a`<span class="sec-badge critical">${e} critical</span>`:p}
416
+ ${r>0?a`<span class="sec-badge warning">${r} warning</span>`:p}
417
+ ${i>0?a`<span class="sec-badge info">${i} info</span>`:p}
418
418
  </div>
419
419
  </div>
420
- `}renderOpenGroups(e){let t={},s=[];for(let r of e){let o=r.issue,n=o.rule||o.type;t[n]||(t[n]={rule:n,title:o.title,severity:o.severity,hint:o.hint,items:[]},s.push(n)),t[n].items.push(r);}return s.sort((r,o)=>{let n=q[t[r].severity]?.sort??2,l=q[t[o].severity]?.sort??2;return n!==l?n-l:t[o].items.length-t[r].items.length}),a`${s.map(r=>this.renderGroup(t[r]))}`}renderGroup(e){let t=q[e.severity]||q.info;return a`
420
+ `}renderOpenGroups(s){let t={},e=[];for(let r of s){let i=r.issue,n=i.rule||i.type;t[n]||(t[n]={rule:n,title:i.title,severity:i.severity,hint:i.hint,items:[]},e.push(n)),t[n].items.push(r);}return e.sort((r,i)=>{let n=Z[t[r].severity]?.sort??2,l=Z[t[i].severity]?.sort??2;return n!==l?n-l:t[i].items.length-t[r].items.length}),a`${e.map(r=>this.renderGroup(t[r]))}`}renderGroup(s){let t=Z[s.severity]||Z.info;return a`
421
421
  <div class="sec-group">
422
422
  <div class="sec-group-header">
423
423
  <span class="sec-group-icon ${t.cls}">${t.icon}</span>
424
- <span class="sec-group-title">${e.title}</span>
425
- <span class="sec-group-count">${e.items.length}</span>
424
+ <span class="sec-group-title">${s.title}</span>
425
+ <span class="sec-group-count">${s.items.length}</span>
426
426
  </div>
427
- ${e.hint?a`<div class="sec-hint">${e.hint}</div>`:d}
428
- <div class="sec-items">${e.items.map(s=>this.renderIssueItem(s))}</div>
427
+ ${s.hint?a`<div class="sec-hint">${s.hint}</div>`:p}
428
+ <div class="sec-items">${s.items.map(e=>this.renderIssueItem(e))}</div>
429
429
  </div>
430
- `}renderIssueItem(e){let t=e.issue;return a`
430
+ `}renderIssueItem(s){let t=s.issue;return a`
431
431
  <div class="sec-item">
432
432
  <div class="sec-item-desc">${t.desc}</div>
433
- ${e.occurrences>1?a`<span class="sec-item-count">${e.occurrences}x</span>`:d}
434
- ${e.state==="fixing"&&e.aiStatus==="fixed"?a`<span class="sec-ai-badge sec-ai-fixing">AI fixed \u2014 awaiting verification</span>`:e.aiStatus==="wont_fix"?a`<span class="sec-ai-badge sec-ai-wontfix">AI: won\u2019t fix</span>`:e.state==="regressed"?a`<span class="sec-ai-badge sec-ai-fixing" style="background:var(--red)">regressed</span>`:d}
435
- ${e.aiNotes?a`<div class="sec-ai-notes">${e.aiNotes}</div>`:d}
433
+ ${s.occurrences>1?a`<span class="sec-item-count">${s.occurrences}x</span>`:p}
434
+ ${s.state==="fixing"&&s.aiStatus==="fixed"?a`<span class="sec-ai-badge sec-ai-fixing">AI fixed \u2014 awaiting verification</span>`:s.aiStatus==="wont_fix"?a`<span class="sec-ai-badge sec-ai-wontfix">AI: won\u2019t fix</span>`:s.state==="regressed"?a`<span class="sec-ai-badge sec-ai-fixing" style="background:var(--red)">regressed</span>`:p}
435
+ ${s.aiNotes?a`<div class="sec-ai-notes">${s.aiNotes}</div>`:p}
436
436
  </div>
437
- `}renderResolved(e){return a`
437
+ `}renderResolved(s){return a`
438
438
  <div class="sec-resolved-title">
439
439
  <span class="sec-resolved-check">\u2713</span> Resolved
440
- <span class="sec-resolved-count">${e.length}</span>
440
+ <span class="sec-resolved-count">${s.length}</span>
441
441
  </div>
442
442
  <div class="sec-group sec-group-resolved">
443
443
  <div class="sec-items">
444
- ${e.map(t=>a`
444
+ ${s.map(t=>a`
445
445
  <div class="sec-item sec-item-resolved">
446
446
  <span class="sec-resolved-item-icon">\u2713</span>
447
447
  <div class="sec-item-desc">${t.issue.title} \u2014 ${t.issue.endpoint||"global"}</div>
448
- ${t.aiStatus==="fixed"?a`<span class="sec-ai-badge sec-ai-verified">Verified fix</span>`:d}
449
- ${t.aiNotes?a`<div class="sec-ai-notes">${t.aiNotes}</div>`:d}
448
+ ${t.aiStatus==="fixed"?a`<span class="sec-ai-badge sec-ai-verified">Verified fix</span>`:p}
449
+ ${t.aiNotes?a`<div class="sec-ai-notes">${t.aiNotes}</div>`:p}
450
450
  </div>
451
451
  `)}
452
452
  </div>
453
453
  </div>
454
- `}};u([R({context:x})],Ct.prototype,"store",2),Ct=u([g("bk-security-view")],Ct);var pt=class extends f{constructor(){super(...arguments);this.expandedCardIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleCard(t){this.expandedCardIdx=this.expandedCardIdx===t?-1:t;}render(){let t=this.store.state,s=t.requests.filter(b=>!b.isStatic&&!b.isHealthCheck&&(!b.path||b.path.indexOf(N)!==0));if(!(s.length>0||t.queries.length>0||t.errors.length>0))return a`<bk-empty-state
454
+ `}};u([I({context:A})],Vt.prototype,"store",2),Vt=u([S("bk-security-view")],Vt);var Rt=class extends E{constructor(){super(...arguments);this.expandedCardIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}toggleCard(t){this.expandedCardIdx=this.expandedCardIdx===t?-1:t;}render(){let t=this.store.state,e=t.requests.filter(y=>!y.isStatic&&!y.isHealthCheck&&(!y.path||y.path.indexOf(F)!==0));if(!(e.length>0||t.queries.length>0||t.errors.length>0))return a`<bk-empty-state
455
455
  title="Waiting for requests..."
456
456
  subtitle="Start using your app to see insights here"
457
- ></bk-empty-state>`;let o=s.filter(b=>b.statusCode>=400).length,n=new Set(["data-fetch","api-call","server-action","page-load"]),l=s.filter(b=>b.category&&n.has(b.category)),c=l.length>0?l:s,p=c.length>0?Math.round(c.reduce((b,It)=>b+It.durationMs,0)/c.length):0,h=t.issues||[],m=h.filter(b=>b.state==="open"||b.state==="regressed"),E=h.filter(b=>b.state==="fixing"),T=h.filter(b=>b.state==="resolved");return a`
457
+ ></bk-empty-state>`;let i=e.filter(y=>y.statusCode>=400).length,n=new Set(["data-fetch","api-call","server-action","page-load"]),l=e.filter(y=>y.category&&n.has(y.category)),c=l.length>0?l:e,d=c.length>0?Math.round(c.reduce((y,k)=>y+k.durationMs,0)/c.length):0,h=t.issues||[],m=h.filter(y=>y.state==="open"||y.state==="regressed"),v=h.filter(y=>y.state==="fixing"),x=h.filter(y=>y.state==="resolved");return a`
458
458
  <div class="ov-container" id="overview-content">
459
- ${this.renderSummary(s.length,t.flows.length,p,t.queries.length,o,t.fetches.length)}
460
- ${m.length===0&&E.length===0&&T.length===0?a`<div class="ov-clear">
459
+ ${this.renderSummary(e.length,t.flows.length,d,t.queries.length,i,t.fetches.length)}
460
+ ${m.length===0&&v.length===0&&x.length===0?a`<div class="ov-clear">
461
461
  <span class="ov-clear-icon">\u2713</span>All clear \u2014 no issues detected
462
- </div>`:d}
463
- ${m.length===0&&T.length>0?a`<div class="ov-clear">
462
+ </div>`:p}
463
+ ${m.length===0&&x.length>0?a`<div class="ov-clear">
464
464
  <span class="ov-clear-icon">\u2713</span>All issues resolved \u2014
465
- ${T.length} finding${T.length!==1?"s were":" was"} detected and
465
+ ${x.length} finding${x.length!==1?"s were":" was"} detected and
466
466
  fixed
467
- </div>`:d}
468
- ${m.length>0?this.renderOpenIssues(m):d}
469
- ${E.length>0?this.renderVerifying(E):d}
470
- ${T.length>0?this.renderResolvedIssues(T):d}
467
+ </div>`:p}
468
+ ${m.length>0?this.renderOpenIssues(m):p}
469
+ ${v.length>0?this.renderVerifying(v):p}
470
+ ${x.length>0?this.renderResolvedIssues(x):p}
471
471
  </div>
472
- `}renderSummary(t,s,r,o,n,l){return a`
472
+ `}renderSummary(t,e,r,i,n,l){return a`
473
473
  <div class="ov-summary">
474
474
  <div class="ov-stat"><span class="ov-stat-value">${t}</span><span class="ov-stat-label">Requests</span></div>
475
- <div class="ov-stat"><span class="ov-stat-value">${s}</span><span class="ov-stat-label">Actions</span></div>
476
- <div class="ov-stat"><span class="ov-stat-value">${v(r)}</span><span class="ov-stat-label">Avg Response</span></div>
477
- <div class="ov-stat"><span class="ov-stat-value">${o}</span><span class="ov-stat-label">Queries</span></div>
475
+ <div class="ov-stat"><span class="ov-stat-value">${e}</span><span class="ov-stat-label">Actions</span></div>
476
+ <div class="ov-stat"><span class="ov-stat-value">${_(r)}</span><span class="ov-stat-label">Avg Response</span></div>
477
+ <div class="ov-stat"><span class="ov-stat-value">${i}</span><span class="ov-stat-label">Queries</span></div>
478
478
  <div class="ov-stat"><span class="ov-stat-value" style="color:${n>0?"var(--red)":"var(--green)"}">${n}</span><span class="ov-stat-label">Errors</span></div>
479
479
  <div class="ov-stat"><span class="ov-stat-value">${l}</span><span class="ov-stat-label">Fetches</span></div>
480
480
  </div>
481
481
  `}renderOpenIssues(t){return a`
482
482
  <div class="ov-section-title">Issues Found <span class="ov-issue-count">${t.length}</span></div>
483
- <div class="ov-cards">${t.map((s,r)=>this.renderIssueCard(s,r))}</div>
484
- `}renderIssueCard(t,s){let r=t.issue,o=q[r.severity]||q.info,n=this.expandedCardIdx===s,l=t.aiStatus==="wont_fix"?a`<span class="sec-ai-badge sec-ai-wontfix">AI: won\u2019t fix</span>`:t.state==="regressed"?a`<span class="sec-ai-badge sec-ai-fixing" style="background:var(--red)">regressed</span>`:d,c=t.cleanHitsSinceLastSeen>0?a`<div class="ov-card-resolving">Resolving\u2026 ${t.cleanHitsSinceLastSeen}/${5} clean requests</div>`:d;return a`
485
- <div class="ov-card ${n?"expanded":""}" @click=${()=>this.toggleCard(s)}>
486
- <span class="ov-card-icon ${o.cls}">${o.icon}</span>
483
+ <div class="ov-cards">${t.map((e,r)=>this.renderIssueCard(e,r))}</div>
484
+ `}renderIssueCard(t,e){let r=t.issue,i=Z[r.severity]||Z.info,n=this.expandedCardIdx===e,l=t.aiStatus==="wont_fix"?a`<span class="sec-ai-badge sec-ai-wontfix">AI: won\u2019t fix</span>`:t.state==="regressed"?a`<span class="sec-ai-badge sec-ai-fixing" style="background:var(--red)">regressed</span>`:p,c=t.cleanHitsSinceLastSeen>0?a`<div class="ov-card-resolving">Resolving\u2026 ${t.cleanHitsSinceLastSeen}/${5} clean requests</div>`:p;return a`
485
+ <div class="ov-card ${n?"expanded":""}" @click=${()=>this.toggleCard(e)}>
486
+ <span class="ov-card-icon ${i.cls}">${i.icon}</span>
487
487
  <div class="ov-card-body">
488
488
  <div class="ov-card-title">${r.title}${l}</div>
489
489
  <div class="ov-card-desc">${r.desc}</div>
490
- ${r.detail?a`<div class="ov-card-detail">${r.detail}</div>`:d}
490
+ ${r.detail?a`<div class="ov-card-detail">${r.detail}</div>`:p}
491
491
  ${c}
492
- ${n&&r.hint?a`<div class="ov-card-hint">${r.hint}</div>`:d}
492
+ ${n&&r.hint?a`<div class="ov-card-hint">${r.hint}</div>`:p}
493
493
  </div>
494
- ${r.hint?a`<span class="ov-card-arrow">${n?"\u2193":"\u2192"}</span>`:d}
494
+ ${r.hint?a`<span class="ov-card-arrow">${n?"\u2193":"\u2192"}</span>`:p}
495
495
  </div>
496
496
  `}renderVerifying(t){return a`
497
497
  <div class="ov-section-title ov-resolved-title">
@@ -499,7 +499,7 @@
499
499
  <span class="ov-issue-count">${t.length}</span>
500
500
  </div>
501
501
  <div class="ov-cards">
502
- ${t.map(s=>{let r=s.issue,o=s.cleanHitsSinceLastSeen>0?a`<div class="ov-card-resolving">Verifying\u2026 ${s.cleanHitsSinceLastSeen}/${5} clean requests</div>`:d;return a`
502
+ ${t.map(e=>{let r=e.issue,i=e.cleanHitsSinceLastSeen>0?a`<div class="ov-card-resolving">Verifying\u2026 ${e.cleanHitsSinceLastSeen}/${5} clean requests</div>`:p;return a`
503
503
  <div class="ov-card ov-card-resolved">
504
504
  <span class="ov-card-icon resolved">\u29d7</span>
505
505
  <div class="ov-card-body">
@@ -508,7 +508,7 @@
508
508
  <span class="sec-ai-badge sec-ai-fixing">AI fixed \u2014 awaiting verification</span>
509
509
  </div>
510
510
  <div class="ov-card-desc">${r.desc}</div>
511
- ${o}
511
+ ${i}
512
512
  </div>
513
513
  </div>
514
514
  `})}
@@ -519,46 +519,46 @@
519
519
  <span class="ov-issue-count">${t.length}</span>
520
520
  </div>
521
521
  <div class="ov-cards">
522
- ${t.map(s=>a`
522
+ ${t.map(e=>a`
523
523
  <div class="ov-card ov-card-resolved">
524
524
  <span class="ov-card-icon resolved">\u2713</span>
525
525
  <div class="ov-card-body">
526
- <div class="ov-card-title" style="text-decoration:line-through;color:var(--text-muted)">${s.issue.title}</div>
527
- <div class="ov-card-desc">${s.issue.desc}</div>
526
+ <div class="ov-card-title" style="text-decoration:line-through;color:var(--text-muted)">${e.issue.title}</div>
527
+ <div class="ov-card-desc">${e.issue.desc}</div>
528
528
  </div>
529
529
  </div>
530
530
  `)}
531
531
  </div>
532
- `}};u([R({context:x})],pt.prototype,"store",2),u([_()],pt.prototype,"expandedCardIdx",2),pt=u([g("bk-overview-view")],pt);function hs(i){return i<1?"<1ms":i<1e3?Math.round(i)+"ms":(i/1e3).toFixed(1)+"s"}function ir(i){return i<Z?yt.green:i<tt?yt.amber:yt.red}function nr(i){return i.statusCode>=400?yt.red:ir(i.durationMs)}function ms(i){return [parseInt(i.slice(1,3),16),parseInt(i.slice(3,5),16),parseInt(i.slice(5,7),16)]}function ar(i){let e=i.getContext("2d");if(!e)return null;let t=window.devicePixelRatio||1,s=i.clientWidth,r=i.clientHeight;return i.width=s*t,i.height=r*t,e.scale(t,t),{ctx:e,w:s,h:r}}function lr(i,e,t,s,r){let[o,n,l]=ms(r);i.beginPath(),i.arc(e,t,s+2,0,Math.PI*2),i.fillStyle=`rgba(${o},${n},${l},0.25)`,i.fill(),i.beginPath(),i.arc(e,t,s,0,Math.PI*2),i.fillStyle=r,i.fill();}function cr(i,e,t,s,r,o){let[n,l,c]=ms(r);i.strokeStyle=`rgba(${n},${l},${c},0.3)`,i.lineWidth=o+2,i.beginPath(),i.moveTo(e-s,t-s),i.lineTo(e+s,t+s),i.moveTo(e+s,t-s),i.lineTo(e-s,t+s),i.stroke(),i.strokeStyle=r,i.lineWidth=o,i.beginPath(),i.moveTo(e-s,t-s),i.lineTo(e+s,t+s),i.moveTo(e+s,t-s),i.lineTo(e-s,t+s),i.stroke();}function vs(i,e){let t=[],s=ar(i);if(!s||e.length===0)return t;let{ctx:r,w:o,h:n}=s,l=Ze,c=o-l.left-l.right,p=n-l.top-l.bottom,h=0,m=e[0].timestamp,E=e[0].timestamp;for(let S of e)S.durationMs>h&&(h=S.durationMs),S.timestamp<m&&(m=S.timestamp),S.timestamp>E&&(E=S.timestamp);h=Math.max(h,10),h=Math.ceil(h*1.15/10)*10;let T=E-m||1;r.strokeStyle=ze,r.lineWidth=1;let b=4;for(let S=0;S<=b;S++){let A=l.top+p-S/b*p;r.beginPath(),r.moveTo(l.left,A),r.lineTo(l.left+c,A),r.stroke(),r.fillStyle=ve,r.font=Je,r.textAlign="right",r.fillText(hs(Math.round(S/b*h)),l.left-8,A+3);}for(let S of [{ms:Z},{ms:tt}]){if(S.ms>=h)continue;let A=l.top+p-S.ms/h*p;r.beginPath(),r.setLineDash([4,4]),r.strokeStyle="rgba(113,113,122,0.3)",r.lineWidth=1,r.moveTo(l.left,A),r.lineTo(l.left+c,A),r.stroke(),r.setLineDash([]),r.fillStyle="rgba(113,113,122,0.5)",r.font=fe,r.textAlign="left",r.fillText(hs(S.ms),l.left+c+2,A+3);}for(let S=0;S<e.length;S++){let A=e[S],ut=e.length===1?l.left+c/2:l.left+(A.timestamp-m)/T*c,jt=l.top+p-A.durationMs/h*p,$e=nr(A);t.push({x:ut,y:jt,idx:S,r:A}),A.statusCode>=400?cr(r,ut,jt,4,$e,2):lr(r,ut,jt,4,$e);}r.fillStyle=ve,r.font=fe,r.textAlign="center";let It=[m,m+T/2,E];for(let S=0;S<It.length;S++){let A=l.left+S/2*c,ut=new Date(It[S]);r.fillText(ut.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),A,l.top+p+14);}return t}var vr={max:1/0,label:"Pending",color:"var(--text-muted)",bg:"var(--bg-muted)",border:"var(--border)"};function fs(i,e,t){return t>=20?i:e}function Te(i,e){if(!e||e<=0)return vr;let t=i/e;return t<.7?et[0]:t<1.2?et[1]:t<2?et[2]:t<3?et[3]:et[4]}var M=class extends f{constructor(){super(...arguments);this.selectedEndpoint=H;this.graphData=[];this.loadError=false;this.queryBreakdown=[];this.queryBreakdownLoading=false;this.scatterDots=[];}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate()),this.loadMetrics();}async loadMetrics(){try{let s=await(await fetch($.metricsLive)).json();this.graphData=s.endpoints||[],this.loadError=!1,(!this.selectedEndpoint||this.selectedEndpoint===H)&&(this.selectedEndpoint=H);}catch{this.loadError=true;}}healthGradeForEndpoint(t){let s=fs(t.summary.p95Ms,t.summary.medianMs,t.summary.totalRequests);return Te(s,t.baselineP95Ms)}healthGradeForDuration(t,s){return Te(t,s)}getCallers(t){let s=this.store.state.flows,r=new Map;for(let o of s)for(let n of o.requests)if(`${n.method} ${n.path}`===t||this.normalizeEndpoint(n)===t){let c=r.get(o.label);c?(c.count++,c.totalMs+=n.durationMs):r.set(o.label,{count:1,totalMs:n.durationMs});}return [...r.entries()].map(([o,n])=>({label:o,count:n.count,avgMs:Math.round(n.totalMs/n.count)})).sort((o,n)=>n.count-o.count)}normalizeEndpoint(t){let s=t.path.replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,"/:id").replace(/\/\d+/g,"/:id");return `${t.method} ${s}`}async loadQueryBreakdown(t){if(this.queryBreakdownLoading)return;let r=this.store.state.requests.filter(o=>`${o.method} ${o.path}`===t||this.normalizeEndpoint(o)===t).slice(-20).map(o=>o.id).filter(Boolean);if(r.length===0){this.queryBreakdown=[];return}this.queryBreakdownLoading=true;try{let o=await fetch(`${$.activity}?requestIds=${r.join(",")}`);if(!o.ok){this.queryBreakdownLoading=!1;return}let n=await o.json(),l=new Map;for(let c of Object.values(n.activities))for(let p of c.timeline){if(p.type!=="query")continue;let h=p.data,m=(h.normalizedOp||h.operation||"QUERY").toUpperCase(),E=h.table||h.model||"",T=`${m} ${E}`.trim(),b=l.get(T);b?(b.totalMs+=h.durationMs,b.count++):l.set(T,{label:T,totalMs:h.durationMs,count:1});}this.queryBreakdown=[...l.values()].map(c=>({...c,avgMs:Math.round(c.totalMs/c.count)})).sort((c,p)=>p.totalMs-c.totalMs);}catch{}this.queryBreakdownLoading=false;}renderScatterChart(t,s){this.scatterDots=vs(t,s),t.style.cursor="pointer",t.onclick=r=>{let o=t.getBoundingClientRect(),n=r.clientX-o.left,l=r.clientY-o.top,c=null,p=1/0;for(let h of this.scatterDots){let m=Math.sqrt((h.x-n)**2+(h.y-l)**2);m<p&&(p=m,c=h);}c&&p<16&&this.highlightRow(c.idx);};}highlightRow(t){let s=this.querySelector(".perf-hist-row-hl");s&&s.classList.remove("perf-hist-row-hl");let r=this.querySelector(`[data-req-idx="${t}"]`);r&&(r.classList.add("perf-hist-row-hl"),r.scrollIntoView({behavior:"smooth",block:"center"}));}updated(){if(this.selectedEndpoint===H)return;let t=this.querySelector("#perf-detail-canvas");if(t){let s=this.graphData.find(r=>r.endpoint===this.selectedEndpoint);s&&this.renderScatterChart(t,s.requests);}}render(){return !this.graphData||this.graphData.length===0?a`<bk-empty-state title="No performance data yet" subtitle="Hit some endpoints and data will appear here"></bk-empty-state>`:a`
532
+ `}};u([I({context:A})],Rt.prototype,"store",2),u([b()],Rt.prototype,"expandedCardIdx",2),Rt=u([S("bk-overview-view")],Rt);function Ys(o){return o<1?"<1ms":o<1e3?Math.round(o)+"ms":(o/1e3).toFixed(1)+"s"}function oi(o){return o<mt?Bt.green:o<ft?Bt.amber:Bt.red}function ni(o){return o.statusCode>=400?Bt.red:oi(o.durationMs)}function Xs(o){return [parseInt(o.slice(1,3),16),parseInt(o.slice(3,5),16),parseInt(o.slice(5,7),16)]}function ai(o){let s=o.getContext("2d");if(!s)return null;let t=window.devicePixelRatio||1,e=o.clientWidth,r=o.clientHeight;return o.width=e*t,o.height=r*t,s.scale(t,t),{ctx:s,w:e,h:r}}function li(o,s,t,e,r){let[i,n,l]=Xs(r);o.beginPath(),o.arc(s,t,e+2,0,Math.PI*2),o.fillStyle=`rgba(${i},${n},${l},0.25)`,o.fill(),o.beginPath(),o.arc(s,t,e,0,Math.PI*2),o.fillStyle=r,o.fill();}function ci(o,s,t,e,r,i){let[n,l,c]=Xs(r);o.strokeStyle=`rgba(${n},${l},${c},0.3)`,o.lineWidth=i+2,o.beginPath(),o.moveTo(s-e,t-e),o.lineTo(s+e,t+e),o.moveTo(s+e,t-e),o.lineTo(s-e,t+e),o.stroke(),o.strokeStyle=r,o.lineWidth=i,o.beginPath(),o.moveTo(s-e,t-e),o.lineTo(s+e,t+e),o.moveTo(s+e,t-e),o.lineTo(s-e,t+e),o.stroke();}function Vs(o,s){let t=[],e=ai(o);if(!e||s.length===0)return t;let{ctx:r,w:i,h:n}=e,l=Ls,c=i-l.left-l.right,d=n-l.top-l.bottom,h=0,m=s[0].timestamp,v=s[0].timestamp;for(let $ of s)$.durationMs>h&&(h=$.durationMs),$.timestamp<m&&(m=$.timestamp),$.timestamp>v&&(v=$.timestamp);h=Math.max(h,10),h=Math.ceil(h*1.15/10)*10;let x=v-m||1;r.strokeStyle=Is,r.lineWidth=1;let y=4;for(let $=0;$<=y;$++){let f=l.top+d-$/y*d;r.beginPath(),r.moveTo(l.left,f),r.lineTo(l.left+c,f),r.stroke(),r.fillStyle=Ue,r.font=Cs,r.textAlign="right",r.fillText(Ys(Math.round($/y*h)),l.left-8,f+3);}for(let $ of [{ms:mt},{ms:ft}]){if($.ms>=h)continue;let f=l.top+d-$.ms/h*d;r.beginPath(),r.setLineDash([4,4]),r.strokeStyle="rgba(113,113,122,0.3)",r.lineWidth=1,r.moveTo(l.left,f),r.lineTo(l.left+c,f),r.stroke(),r.setLineDash([]),r.fillStyle="rgba(113,113,122,0.5)",r.font=Fe,r.textAlign="left",r.fillText(Ys($.ms),l.left+c+2,f+3);}for(let $=0;$<s.length;$++){let f=s[$],g=s.length===1?l.left+c/2:l.left+(f.timestamp-m)/x*c,T=l.top+d-f.durationMs/h*d,R=ni(f);t.push({x:g,y:T,idx:$,r:f}),f.statusCode>=400?ci(r,g,T,4,R,2):li(r,g,T,4,R);}r.fillStyle=Ue,r.font=Fe,r.textAlign="center";let k=[m,m+x/2,v];for(let $=0;$<k.length;$++){let f=l.left+$/2*c,g=new Date(k[$]);r.fillText(g.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),f,l.top+d+14);}return t}var fi={max:1/0,label:"Pending",color:"var(--text-muted)",bg:"var(--bg-muted)",border:"var(--border)"};function Ks(o,s,t){return t>=20?o:s}function Ye(o,s){if(!s||s<=0)return fi;let t=o/s;return t<.7?gt[0]:t<1.2?gt[1]:t<2?gt[2]:t<3?gt[3]:gt[4]}var Q=class extends E{constructor(){super(...arguments);this.selectedEndpoint=J;this.graphData=[];this.loadError=false;this.queryBreakdown=[];this.queryBreakdownLoading=false;this.scatterDots=[];}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate()),this.loadMetrics();}async loadMetrics(){try{let e=await(await fetch(w.metricsLive)).json();this.graphData=e.endpoints||[],this.loadError=!1,(!this.selectedEndpoint||this.selectedEndpoint===J)&&(this.selectedEndpoint=J);}catch{this.loadError=true;}}healthGradeForEndpoint(t){let e=Ks(t.summary.p95Ms,t.summary.medianMs,t.summary.totalRequests);return Ye(e,t.baselineP95Ms)}healthGradeForDuration(t,e){return Ye(t,e)}getCallers(t){let e=this.store.state.flows,r=new Map;for(let i of e)for(let n of i.requests)if(`${n.method} ${n.path}`===t||this.normalizeEndpoint(n)===t){let c=r.get(i.label);c?(c.count++,c.totalMs+=n.durationMs):r.set(i.label,{count:1,totalMs:n.durationMs});}return [...r.entries()].map(([i,n])=>({label:i,count:n.count,avgMs:Math.round(n.totalMs/n.count)})).sort((i,n)=>n.count-i.count)}normalizeEndpoint(t){let r=t.path.split("?")[0].split("/").map(i=>{if(!i)return i;let n=i.length>0;for(let l=0;l<i.length;l++){let c=i.charCodeAt(l);if(c<48||c>57){n=false;break}}return n||i.length===36&&i[8]==="-"&&i[13]==="-"&&i[18]==="-"&&i[23]==="-"?":id":i}).join("/");return `${t.method} ${r}`}async loadQueryBreakdown(t){if(this.queryBreakdownLoading)return;let r=this.store.state.requests.filter(i=>`${i.method} ${i.path}`===t||this.normalizeEndpoint(i)===t).slice(-20).map(i=>i.id).filter(Boolean);if(r.length===0){this.queryBreakdown=[];return}this.queryBreakdownLoading=true;try{let i=await fetch(`${w.activity}?requestIds=${r.join(",")}`);if(!i.ok){this.queryBreakdownLoading=!1;return}let n=await i.json(),l=new Map;for(let c of Object.values(n.activities))for(let d of c.timeline){if(d.type!=="query")continue;let h=d.data,m=(h.normalizedOp||h.operation||"QUERY").toUpperCase(),v=h.table||h.model||"",x=`${m} ${v}`.trim(),y=l.get(x);y?(y.totalMs+=h.durationMs,y.count++):l.set(x,{label:x,totalMs:h.durationMs,count:1});}this.queryBreakdown=[...l.values()].map(c=>({...c,avgMs:Math.round(c.totalMs/c.count)})).sort((c,d)=>d.totalMs-c.totalMs);}catch{}this.queryBreakdownLoading=false;}renderScatterChart(t,e){this.scatterDots=Vs(t,e),t.style.cursor="pointer",t.onclick=r=>{let i=t.getBoundingClientRect(),n=r.clientX-i.left,l=r.clientY-i.top,c=null,d=1/0;for(let h of this.scatterDots){let m=Math.sqrt((h.x-n)**2+(h.y-l)**2);m<d&&(d=m,c=h);}c&&d<16&&this.highlightRow(c.idx);};}highlightRow(t){let e=this.querySelector(".perf-hist-row-hl");e&&e.classList.remove("perf-hist-row-hl");let r=this.querySelector(`[data-req-idx="${t}"]`);r&&(r.classList.add("perf-hist-row-hl"),r.scrollIntoView({behavior:"smooth",block:"center"}));}updated(){if(this.selectedEndpoint===J)return;let t=this.querySelector("#perf-detail-canvas");if(t){let e=this.graphData.find(r=>r.endpoint===this.selectedEndpoint);e&&this.renderScatterChart(t,e.requests);}}render(){return !this.graphData||this.graphData.length===0?a`<bk-empty-state title="No performance data yet" subtitle="Hit some endpoints and data will appear here"></bk-empty-state>`:a`
533
533
  <div id="graph-content">
534
534
  ${this.renderSelector()}
535
- ${this.selectedEndpoint===H?this.renderOverview():this.renderDetail()}
535
+ ${this.selectedEndpoint===J?this.renderOverview():this.renderDetail()}
536
536
  </div>
537
537
  `}renderSelector(){return a`
538
538
  <div class="perf-selector">
539
- <button class="perf-selector-btn ${this.selectedEndpoint===H?"active":""}"
540
- @click=${()=>{this.selectedEndpoint=H;}}>Overview</button>
541
- ${this.graphData.map((t,s)=>a`
539
+ <button class="perf-selector-btn ${this.selectedEndpoint===J?"active":""}"
540
+ @click=${()=>{this.selectedEndpoint=J;}}>Overview</button>
541
+ ${this.graphData.map((t,e)=>a`
542
542
  <button class="perf-selector-btn ${t.endpoint===this.selectedEndpoint?"active":""}"
543
543
  @click=${()=>{this.selectedEndpoint=t.endpoint,this.queryBreakdown=[],this.loadQueryBreakdown(t.endpoint);}}>
544
- <span class="perf-dot" style="background:${me[s%me.length]}"></span>${t.endpoint}
544
+ <span class="perf-dot" style="background:${qe[e%qe.length]}"></span>${t.endpoint}
545
545
  </button>
546
546
  `)}
547
547
  </div>
548
- `}renderOverview(){let t=this.graphData.filter(c=>c.requests.length>0);if(t.length===0)return d;let s=t.reduce((c,p)=>c+p.summary.totalRequests,0),r=s>0?Math.round(t.reduce((c,p)=>c+p.summary.p95Ms*p.summary.totalRequests,0)/s):0,o=t.reduce((c,p)=>c+Math.round(p.summary.errorRate*p.summary.totalRequests),0),n=s>0?o/s:0,l=t[0];return a`
548
+ `}renderOverview(){let t=this.graphData.filter(c=>c.requests.length>0);if(t.length===0)return p;let e=t.reduce((c,d)=>c+d.summary.totalRequests,0),r=e>0?Math.round(t.reduce((c,d)=>c+d.summary.p95Ms*d.summary.totalRequests,0)/e):0,i=t.reduce((c,d)=>c+Math.round(d.summary.errorRate*d.summary.totalRequests),0),n=e>0?i/e:0,l=t[0];return a`
549
549
  <div class="perf-overview">
550
550
  <div class="perf-summary-row">
551
551
  <div class="perf-summary-card">
552
552
  <span class="perf-summary-label">Total Requests</span>
553
- <span class="perf-summary-value">${s}</span>
553
+ <span class="perf-summary-value">${e}</span>
554
554
  </div>
555
555
  <div class="perf-summary-card">
556
556
  <span class="perf-summary-label">Avg P95</span>
557
- <span class="perf-summary-value" style="color:${this.healthGradeForDuration(r).color}">${v(r)}</span>
557
+ <span class="perf-summary-value" style="color:${this.healthGradeForDuration(r).color}">${_(r)}</span>
558
558
  </div>
559
559
  <div class="perf-summary-card">
560
560
  <span class="perf-summary-label">Error Rate</span>
561
- <span class="perf-summary-value" style="color:${o>0?"var(--red)":"var(--green)"}">${Math.round(n*100)}%</span>
561
+ <span class="perf-summary-value" style="color:${i>0?"var(--red)":"var(--green)"}">${Math.round(n*100)}%</span>
562
562
  </div>
563
563
  <div class="perf-summary-card">
564
564
  <span class="perf-summary-label">Slowest</span>
@@ -582,45 +582,45 @@
582
582
  </tbody>
583
583
  </table>
584
584
  </div>
585
- `}renderHeatmapRow(t){let s=t.summary,r=this.healthGradeForEndpoint(t),o=Math.round(s.errorRate*s.totalRequests),n=(s.avgQueryTimeMs||0)+(s.avgFetchTimeMs||0)+(s.avgAppTimeMs||0),l=0,c=0,p=100;return n>0&&(l=Math.round((s.avgQueryTimeMs||0)/n*100),c=Math.round((s.avgFetchTimeMs||0)/n*100),p=Math.max(0,100-l-c)),a`
585
+ `}renderHeatmapRow(t){let e=t.summary,r=this.healthGradeForEndpoint(t),i=Math.round(e.errorRate*e.totalRequests),n=(e.avgQueryTimeMs||0)+(e.avgFetchTimeMs||0)+(e.avgAppTimeMs||0),l=0,c=0,d=100;return n>0&&(l=Math.round((e.avgQueryTimeMs||0)/n*100),c=Math.round((e.avgFetchTimeMs||0)/n*100),d=Math.max(0,100-l-c)),a`
586
586
  <tr class="perf-table-row" @click=${()=>{this.selectedEndpoint=t.endpoint,this.queryBreakdown=[],this.loadQueryBreakdown(t.endpoint);}}>
587
587
  <td class="perf-td-name">${t.endpoint}</td>
588
- <td class="perf-td-right">${s.totalRequests}</td>
588
+ <td class="perf-td-right">${e.totalRequests}</td>
589
589
  <td class="perf-td-center">
590
- <span class="perf-hm-p95" style="color:${r.color};background:${r.bg};border-color:${r.border}">${v(s.p95Ms)}</span>
590
+ <span class="perf-hm-p95" style="color:${r.color};background:${r.bg};border-color:${r.border}">${_(e.p95Ms)}</span>
591
591
  </td>
592
- <td class="perf-td-center" style="color:${o>0?"var(--red)":"var(--text-muted)"}">${o>0?o:"-"}</td>
593
- <td class="perf-td-center" style="color:${s.avgQueryCount>5?"var(--amber)":"var(--text-muted)"}">${s.avgQueryCount}</td>
592
+ <td class="perf-td-center" style="color:${i>0?"var(--red)":"var(--text-muted)"}">${i>0?i:"-"}</td>
593
+ <td class="perf-td-center" style="color:${e.avgQueryCount>5?"var(--amber)":"var(--text-muted)"}">${e.avgQueryCount}</td>
594
594
  <td>
595
595
  <span class="perf-hm-split-bar">
596
- ${l>0?a`<span class="perf-breakdown-seg perf-breakdown-db" style="width:${l}%"></span>`:d}
597
- ${c>0?a`<span class="perf-breakdown-seg perf-breakdown-fetch" style="width:${c}%"></span>`:d}
598
- ${p>0?a`<span class="perf-breakdown-seg perf-breakdown-app" style="width:${p}%"></span>`:d}
596
+ ${l>0?a`<span class="perf-breakdown-seg perf-breakdown-db" style="width:${l}%"></span>`:p}
597
+ ${c>0?a`<span class="perf-breakdown-seg perf-breakdown-fetch" style="width:${c}%"></span>`:p}
598
+ ${d>0?a`<span class="perf-breakdown-seg perf-breakdown-app" style="width:${d}%"></span>`:p}
599
599
  </span>
600
600
  </td>
601
601
  </tr>
602
- `}renderDetail(){let t=this.graphData.find(n=>n.endpoint===this.selectedEndpoint);if(!t?.requests?.length)return a`<bk-empty-state subtitle="No data for this endpoint"></bk-empty-state>`;let s=t.summary,r=this.healthGradeForEndpoint(t),o=Math.round(s.errorRate*s.totalRequests);return a`
602
+ `}renderDetail(){let t=this.graphData.find(n=>n.endpoint===this.selectedEndpoint);if(!t?.requests?.length)return a`<bk-empty-state subtitle="No data for this endpoint"></bk-empty-state>`;let e=t.summary,r=this.healthGradeForEndpoint(t),i=Math.round(e.errorRate*e.totalRequests);return a`
603
603
  ${this.renderDetailHeader(t,r)}
604
- ${this.renderDetailMetrics(s,r,o)}
605
- ${this.renderDetailBreakdown(s)}
604
+ ${this.renderDetailMetrics(e,r,i)}
605
+ ${this.renderDetailBreakdown(e)}
606
606
  ${this.renderCallers(t.endpoint)}
607
607
  ${this.renderQueryBreakdown()}
608
608
  ${this.renderTrends(t)}
609
609
  ${this.renderDetailChart()}
610
610
  ${this.renderDetailHistory(t)}
611
- `}renderDetailHeader(t,s){return a`
611
+ `}renderDetailHeader(t,e){return a`
612
612
  <div class="perf-detail-header">
613
613
  <div class="perf-detail-title">
614
- <span class="perf-badge perf-badge-lg" style="color:${s.color};background:${s.bg};border-color:${s.border}">${s.label}</span>
614
+ <span class="perf-badge perf-badge-lg" style="color:${e.color};background:${e.bg};border-color:${e.border}">${e.label}</span>
615
615
  <span>${t.endpoint}</span>
616
- ${t.baselineP95Ms?a`<span class="perf-baseline-hint">Baseline: ${v(t.baselineP95Ms)}</span>`:d}
616
+ ${t.baselineP95Ms?a`<span class="perf-baseline-hint">Baseline: ${_(t.baselineP95Ms)}</span>`:p}
617
617
  </div>
618
618
  </div>
619
- `}renderDetailMetrics(t,s,r){return a`
619
+ `}renderDetailMetrics(t,e,r){return a`
620
620
  <div class="perf-metric-row">
621
621
  <div class="perf-metric-card">
622
622
  <span class="perf-metric-label">P95</span>
623
- <span class="perf-metric-value" style="color:${s.color}">${v(t.p95Ms)}</span>
623
+ <span class="perf-metric-value" style="color:${e.color}">${_(t.p95Ms)}</span>
624
624
  </div>
625
625
  <div class="perf-metric-card">
626
626
  <span class="perf-metric-label">Errors</span>
@@ -633,71 +633,71 @@
633
633
  <span class="perf-metric-value" style="color:${t.avgQueryCount>5?"var(--amber)":"var(--text)"}">${t.avgQueryCount}</span>
634
634
  </div>
635
635
  </div>
636
- `}renderDetailBreakdown(t){let s=(t.avgQueryTimeMs||0)+(t.avgFetchTimeMs||0)+(t.avgAppTimeMs||0);if(s<=0)return d;let r=Math.round((t.avgQueryTimeMs||0)/s*100),o=Math.round((t.avgFetchTimeMs||0)/s*100),n=Math.max(0,100-r-o);return a`
636
+ `}renderDetailBreakdown(t){let e=(t.avgQueryTimeMs||0)+(t.avgFetchTimeMs||0)+(t.avgAppTimeMs||0);if(e<=0)return p;let r=Math.round((t.avgQueryTimeMs||0)/e*100),i=Math.round((t.avgFetchTimeMs||0)/e*100),n=Math.max(0,100-r-i);return a`
637
637
  <div class="perf-breakdown">
638
638
  <div class="perf-section-title">Time Breakdown</div>
639
639
  <div class="perf-breakdown-bar">
640
- ${r>0?a`<div class="perf-breakdown-seg perf-breakdown-db" style="width:${r}%"></div>`:d}
641
- ${o>0?a`<div class="perf-breakdown-seg perf-breakdown-fetch" style="width:${o}%"></div>`:d}
642
- ${n>0?a`<div class="perf-breakdown-seg perf-breakdown-app" style="width:${n}%"></div>`:d}
640
+ ${r>0?a`<div class="perf-breakdown-seg perf-breakdown-db" style="width:${r}%"></div>`:p}
641
+ ${i>0?a`<div class="perf-breakdown-seg perf-breakdown-fetch" style="width:${i}%"></div>`:p}
642
+ ${n>0?a`<div class="perf-breakdown-seg perf-breakdown-app" style="width:${n}%"></div>`:p}
643
643
  </div>
644
644
  <div class="perf-breakdown-legend">
645
- <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-db"></span>DB ${v(t.avgQueryTimeMs||0)} (${r}%)</span>
646
- <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-fetch"></span>Fetch ${v(t.avgFetchTimeMs||0)} (${o}%)</span>
647
- <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-app"></span>App ${v(t.avgAppTimeMs||0)} (${n}%)</span>
645
+ <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-db"></span>DB ${_(t.avgQueryTimeMs||0)} (${r}%)</span>
646
+ <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-fetch"></span>Fetch ${_(t.avgFetchTimeMs||0)} (${i}%)</span>
647
+ <span class="perf-breakdown-item"><span class="perf-breakdown-dot perf-breakdown-app"></span>App ${_(t.avgAppTimeMs||0)} (${n}%)</span>
648
648
  </div>
649
649
  </div>
650
- `}renderCallers(t){let s=this.getCallers(t);return s.length===0?d:a`
650
+ `}renderCallers(t){let e=this.getCallers(t);return e.length===0?p:a`
651
651
  <div class="perf-callers">
652
652
  <div class="perf-section-title">Called By</div>
653
653
  <div class="perf-callers-list">
654
- ${s.map(r=>a`
654
+ ${e.map(r=>a`
655
655
  <div class="perf-caller-row">
656
656
  <span class="perf-caller-name">${r.label}</span>
657
657
  <span class="perf-caller-count">${r.count} call${r.count!==1?"s":""}</span>
658
- <span class="perf-caller-avg">avg ${v(r.avgMs)}</span>
658
+ <span class="perf-caller-avg">avg ${_(r.avgMs)}</span>
659
659
  </div>
660
660
  `)}
661
661
  </div>
662
662
  </div>
663
- `}renderQueryBreakdown(){return this.queryBreakdownLoading?a`<div class="perf-queries"><div class="perf-section-title">DB Queries</div><div class="perf-queries-loading">Loading...</div></div>`:this.queryBreakdown.length===0?d:a`
663
+ `}renderQueryBreakdown(){return this.queryBreakdownLoading?a`<div class="perf-queries"><div class="perf-section-title">DB Queries</div><div class="perf-queries-loading">Loading...</div></div>`:this.queryBreakdown.length===0?p:a`
664
664
  <div class="perf-queries">
665
665
  <div class="perf-section-title">DB Queries</div>
666
666
  <div class="perf-queries-list">
667
667
  ${this.queryBreakdown.map(t=>a`
668
668
  <div class="perf-query-row">
669
669
  <span class="perf-query-label">${t.label}</span>
670
- <span class="perf-query-avg">avg ${v(t.avgMs)}</span>
670
+ <span class="perf-query-avg">avg ${_(t.avgMs)}</span>
671
671
  <span class="perf-query-count">${t.count} call${t.count!==1?"s":""}</span>
672
672
  </div>
673
673
  `)}
674
674
  </div>
675
675
  </div>
676
- `}renderTrends(t){let s=t.sessions;if(!s||s.length===0)return d;let r=s.slice(-10);return a`
676
+ `}renderTrends(t){let e=t.sessions;if(!e||e.length===0)return p;let r=e.slice(-10);return a`
677
677
  <div class="perf-trends">
678
678
  <div class="perf-section-title">Session Trend</div>
679
679
  <div class="perf-trends-list">
680
- ${r.map((o,n)=>{let l=n>0?r[n-1].p95DurationMs:null,c=l!==null?o.p95DurationMs>l*1.2?"slower":o.p95DurationMs<l*.8?"faster":"":"",p=this.formatTimeAgo(o.startedAt),h=n===r.length-1,m=this.healthGradeForDuration(o.p95DurationMs,t.baselineP95Ms);return a`
680
+ ${r.map((i,n)=>{let l=n>0?r[n-1].p95DurationMs:null,c=l!==null?i.p95DurationMs>l*1.2?"slower":i.p95DurationMs<l*.8?"faster":"":"",d=this.formatTimeAgo(i.startedAt),h=n===r.length-1,m=this.healthGradeForDuration(i.p95DurationMs,t.baselineP95Ms);return a`
681
681
  <div class="perf-trend-row ${h?"perf-trend-current":""}">
682
- <span class="perf-trend-time">${h?"Current":p}</span>
682
+ <span class="perf-trend-time">${h?"Current":d}</span>
683
683
  <span class="perf-trend-p95">
684
684
  <span class="perf-hm-p95" style="color:${m.color};background:${m.bg};border-color:${m.border}">
685
- p95: ${v(o.p95DurationMs)}
685
+ p95: ${_(i.p95DurationMs)}
686
686
  </span>
687
687
  </span>
688
- <span class="perf-trend-reqs">${o.requestCount} req${o.requestCount!==1?"s":""}</span>
689
- <span class="perf-trend-errs" style="color:${o.errorCount>0?"var(--red)":"var(--text-dim)"}">${o.errorCount} err${o.errorCount!==1?"s":""}</span>
690
- ${c?a`<span class="perf-trend-arrow ${c==="slower"?"perf-trend-slower":"perf-trend-faster"}">${c==="slower"?"\u2191 slower":"\u2193 faster"}</span>`:d}
688
+ <span class="perf-trend-reqs">${i.requestCount} req${i.requestCount!==1?"s":""}</span>
689
+ <span class="perf-trend-errs" style="color:${i.errorCount>0?"var(--red)":"var(--text-dim)"}">${i.errorCount} err${i.errorCount!==1?"s":""}</span>
690
+ ${c?a`<span class="perf-trend-arrow ${c==="slower"?"perf-trend-slower":"perf-trend-faster"}">${c==="slower"?"\u2191 slower":"\u2193 faster"}</span>`:p}
691
691
  </div>
692
692
  `})}
693
693
  </div>
694
694
  </div>
695
- `}formatTimeAgo(t){let s=Date.now()-t,r=Math.round(s/6e4);if(r<1)return "just now";if(r<60)return `${r}m ago`;let o=Math.round(r/60);return o<24?`${o}h ago`:`${Math.round(o/24)}d ago`}renderDetailChart(){return a`
695
+ `}formatTimeAgo(t){let e=Date.now()-t,r=Math.round(e/6e4);if(r<1)return "just now";if(r<60)return `${r}m ago`;let i=Math.round(r/60);return i<24?`${i}h ago`:`${Math.round(i/24)}d ago`}renderDetailChart(){return a`
696
696
  <div class="perf-chart-wrap">
697
697
  <div class="perf-section-title">Response Time</div>
698
698
  <canvas id="perf-detail-canvas" class="perf-canvas" style="width:100%;height:240px"></canvas>
699
699
  </div>
700
- `}renderDetailHistory(t){if(t.requests.length===0)return d;let s=[];for(let r=t.requests.length-1;r>=0&&s.length<50;r--)s.push({point:t.requests[r],originalIndex:r});return a`
700
+ `}renderDetailHistory(t){if(t.requests.length===0)return p;let e=[];for(let r=t.requests.length-1;r>=0&&e.length<50;r--)e.push({point:t.requests[r],originalIndex:r});return a`
701
701
  <div class="perf-history-wrap">
702
702
  <table class="perf-table">
703
703
  <thead>
@@ -711,63 +711,363 @@
711
711
  </tr>
712
712
  </thead>
713
713
  <tbody>
714
- ${s.map(r=>this.renderHistoryRow(r.point,r.originalIndex,t.baselineP95Ms))}
714
+ ${e.map(r=>this.renderHistoryRow(r.point,r.originalIndex,t.baselineP95Ms))}
715
715
  </tbody>
716
716
  </table>
717
717
  </div>
718
- `}renderHistoryRow(t,s,r){let o=this.healthGradeForDuration(t.durationMs,r),n=new Date(t.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),l=t.statusCode>=400,c=t.queryTimeMs||0,p=t.fetchTimeMs||0,h=Math.max(0,t.durationMs-c-p);return a`
719
- <tr class="perf-table-row ${l?"perf-row-err":""}" data-req-idx=${s}>
718
+ `}renderHistoryRow(t,e,r){let i=this.healthGradeForDuration(t.durationMs,r),n=new Date(t.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),l=t.statusCode>=400,c=t.queryTimeMs||0,d=t.fetchTimeMs||0,h=Math.max(0,t.durationMs-c-d);return a`
719
+ <tr class="perf-table-row ${l?"perf-row-err":""}" data-req-idx=${e}>
720
720
  <td class="perf-td-muted">${n}</td>
721
721
  <td>
722
- <span class="perf-badge perf-badge-sm" style="color:${o.color};background:${o.bg};border-color:${o.border}">${o.label}</span>
722
+ <span class="perf-badge perf-badge-sm" style="color:${i.color};background:${i.bg};border-color:${i.border}">${i.label}</span>
723
723
  </td>
724
- <td>${v(t.durationMs)}</td>
724
+ <td>${_(t.durationMs)}</td>
725
725
  <td>
726
- ${c>0?a`<span class="perf-bd-tag perf-bd-tag-db">DB ${v(c)}</span>`:d}
727
- ${p>0?a`<span class="perf-bd-tag perf-bd-tag-fetch">Fetch ${v(p)}</span>`:d}
728
- <span class="perf-bd-tag perf-bd-tag-app">App ${v(h)}</span>
726
+ ${c>0?a`<span class="perf-bd-tag perf-bd-tag-db">DB ${_(c)}</span>`:p}
727
+ ${d>0?a`<span class="perf-bd-tag perf-bd-tag-fetch">Fetch ${_(d)}</span>`:p}
728
+ <span class="perf-bd-tag perf-bd-tag-app">App ${_(h)}</span>
729
729
  </td>
730
730
  <td class="perf-td-center" style="color:${l?"var(--red)":"var(--text-muted)"}">${t.statusCode}</td>
731
731
  <td class="perf-td-right perf-td-muted">${t.queryCount}</td>
732
732
  </tr>
733
- `}};u([R({context:x})],M.prototype,"store",2),u([_()],M.prototype,"selectedEndpoint",2),u([_()],M.prototype,"graphData",2),u([_()],M.prototype,"loadError",2),u([_()],M.prototype,"queryBreakdown",2),u([_()],M.prototype,"queryBreakdownLoading",2),M=u([g("bk-performance-view")],M);function _r(i){return i===0?"<1ms":v(i)}var w=class extends f{constructor(){super(...arguments);this.requestId="";this.requestStarted=0;this.data=null;this.loading=false;this.failed=false;this.expandedSqlIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate()),this.requestId&&this.loadTimeline();}async loadTimeline(){if(!this.requestId)return;let t=w.cache.get(this.requestId);if(t){this.data=t;return}this.loading=true;try{let s=await fetch(`${$.activity}?requestId=${this.requestId}`);if(!s.ok){this.failed=!0,this.loading=!1;return}let r=await s.json();if(w.cache.size>=pe){let o=w.cache.keys().next().value;o!==void 0&&w.cache.delete(o);}w.cache.set(this.requestId,r),this.data=r,this.loading=!1;}catch(s){console.debug("[brakit] timeline load failed:",s),this.failed=true,this.loading=false;}}toggleSql(t,s){s.stopPropagation(),this.expandedSqlIdx=this.expandedSqlIdx===t?-1:t;}copySql(t,s){s.stopPropagation(),navigator.clipboard.writeText(t).then(()=>C.show("SQL copied")).catch(()=>C.show("Copy failed"));}render(){if(this.loading)return a`<div class="tl-loading">Loading activity...</div>`;if(this.failed||!this.data||this.data.total===0)return d;let t=this.data,s=t.timeline[0]?.timestamp??0;return a`
733
+ `}};u([I({context:A})],Q.prototype,"store",2),u([b()],Q.prototype,"selectedEndpoint",2),u([b()],Q.prototype,"graphData",2),u([b()],Q.prototype,"loadError",2),u([b()],Q.prototype,"queryBreakdown",2),u([b()],Q.prototype,"queryBreakdownLoading",2),Q=u([S("bk-performance-view")],Q);var Xe={auth:{label:"Auth",color:"#059669",icon:"\u{1F6E1}",tooltip:"Highlight which endpoints require authentication and which are unprotected"},security:{label:"Security",color:"#dc2626",icon:"\u26A0",tooltip:"Show security findings like exposed secrets, token leaks, and PII exposure"},performance:{label:"Perf",color:"#2563eb",icon:"\u26A1",tooltip:"Color endpoints by P95 latency \u2014 green (fast) to red (slow)"},issues:{label:"Issues",color:"#d97706",icon:"\u25CF",tooltip:"Badge endpoints with open issues like N+1 queries or redundant calls"},heat:{label:"Heat",color:"#ef4444",icon:"\u{1F525}",tooltip:"Color nodes and edges by traffic volume \u2014 blue (low) to red (hot)"}},At={action:{fill:"#faf5ff",stroke:"#a855f7",icon:"\u25B6",columnHeader:"ACTIONS"},endpoint:{fill:"#f8fafc",stroke:"#6366f1",icon:"\u26A1",columnHeader:"ENDPOINTS"},table:{fill:"#f0fdf4",stroke:"#16a34a",icon:"\u229E",columnHeader:"TABLES"},external:{fill:"#fffbeb",stroke:"#d97706",icon:"\u25C6",columnHeader:"EXTERNAL"}},fe={triggers:"#a855f7",reads:"#6366f1",writes:"#ef4444",fetches:"#f59e0b",calls:"#22c55e"},yi=100,_i=300,$i=800;function It(o){return o<yi?"#22c55e":o<_i?"#3b82f6":o<$i?"#eab308":"#ef4444"}var xi=.25,Si=.5,Ti=.75;function Ve(o){return o<xi?"#3b82f6":o<Si?"#22c55e":o<Ti?"#eab308":"#ef4444"}var zs="#4338ca",Js="#e0e7ff",Zs="#818cf8",tr="#eef2ff",Ke="#7c3aed",er="#6366f1",ve="#f97316",sr="#ecfdf5",ze="#059669",rr="#fef2f2",Je="#dc2626",ir="#fffbeb",Ze="#d97706",ct="#ef4444",or=.2,nr=3,ts=1.2,Kt=40;var ar=800,lr=500;function Ci(o){return Math.max(140,o.length*7.2+36)}function es(o,s){return Math.round(36+o.stats.requestCount/s*28)}function Li(o){return o.length>0?Math.max(140,...o.map(s=>Ci(s.label))):0}function dr(o,s,t){let e=[];for(let r of s){let i=r.source===o?r.target:r.target===o?r.source:null;if(i){let n=t.get(i);n&&e.push(n.y+n.h/2);}}return e.length>0?e.reduce((r,i)=>r+i,0)/e.length:1/0}function hr(o,s){let t=f=>o.filter(g=>g.type===f).sort((g,T)=>T.stats.requestCount-g.stats.requestCount),e=t("action"),r=t("endpoint"),i=t("table"),n=t("external"),l=Math.max(1,...o.map(f=>f.stats.requestCount)),c=new Map,d=[],h=[],m=50,v=[{type:"action",items:e},{type:"endpoint",items:r},{type:"table",items:i},{type:"external",items:n}];for(let f of v)if(f.items.length>0){let g=Li(f.items);h.push({type:f.type,items:f.items,width:g,x:m}),m+=g+160;}let x=h[0];if(x){let f=74;for(let g of x.items){let T=es(g,l),R={id:g.id,x:x.x,y:f,w:x.width,h:T,label:g.label,type:g.type,stats:g.stats,annotations:g.annotations};d.push(R),c.set(g.id,R),f+=T+10;}}for(let f=1;f<h.length;f++){let g=h[f],T=[...g.items].sort((C,q)=>dr(C.id,s,c)-dr(q.id,s,c)),R=d.filter(C=>C.x===h[f-1].x),H=Math.min(...R.map(C=>C.y)),B=Math.max(...R.map(C=>C.y+C.h))-H,V=T.reduce((C,q)=>C+es(q,l)+10,-10),G=H+Math.max(0,(B-V)/2);for(let C of T){let q=es(C,l),rs={id:C.id,x:g.x,y:G,w:g.width,h:q,label:C.label,type:C.type,stats:C.stats,annotations:C.annotations};d.push(rs),c.set(C.id,rs),G+=q+10;}}let y=[];for(let f of s){let g=c.get(f.source),T=c.get(f.target);if(!g||!T)continue;let R=g.x<T.x,H=R?g.x+g.w:g.x,X=g.y+g.h/2,B=R?T.x:T.x+T.w,V=T.y+T.h/2,G=[];f.stats.frequency>1&&G.push(`${f.stats.frequency}\xD7`),G.push(f.type),f.stats.avgLatencyMs>0&&G.push(`${f.stats.avgLatencyMs}ms`),y.push({key:f.id,sx:H,sy:X,tx:B,ty:V,label:G.join(" \xB7 "),color:fe[f.type]||"#94a3b8",thickness:Math.min(.75+Math.log2(f.stats.frequency+1)*.35,2.5),dashed:f.type==="reads"||f.type==="writes",data:f});}let k=d.reduce((f,g)=>Math.max(f,g.x+g.w),0),$=d.reduce((f,g)=>Math.max(f,g.y+g.h),0);return {nodes:d,edges:y,width:k+100,height:Math.max($+50,250)}}function ur(o){let s=o.charCodeAt(0);return s>=48&&s<=57||s>=65&&s<=70||s>=97&&s<=102}function Mi(o){if(o.length!==36)return false;for(let s=0;s<o.length;s++)if(s===8||s===13||s===18||s===23){if(o[s]!=="-")return false}else if(!ur(o[s]))return false;return true}function Ni(o){if(!o.length)return false;for(let s=0;s<o.length;s++){let t=o.charCodeAt(s);if(t<48||t>57)return false}return true}function Oi(o){if(o.length<12)return false;for(let s=0;s<o.length;s++)if(!ur(o[s]))return false;return true}function ki(o){if(o.length<8)return false;let s=false,t=false;for(let e=0;e<o.length;e++){let r=o.charCodeAt(e);if(r>=65&&r<=90||r>=97&&r<=122)s=true;else if(r>=48&&r<=57)t=true;else if(r!==95&&r!==45)return false}return s&&t}var Di=":id";function Hi(o){return Mi(o)||Ni(o)||Oi(o)||ki(o)?Di:o}function ss(o,s){let t=s.split("?")[0];return `${o} ${t.split("/").map(e=>e&&Hi(e)).join("/")}`}function mr(o,s,t){let e=[...o],r=[...s],i=new Set(e.map(l=>l.id)),n=new Map;for(let l of t){let c=l.label||"Unknown",d=n.get(c);d||(d={endpointKeys:new Set,count:0,totalMs:0},n.set(c,d)),d.count++,d.totalMs+=l.totalDurationMs;for(let h of l.requests)h.path?.startsWith(F)||d.endpointKeys.add(ss(h.method,h.path));}for(let[l,c]of n){let d=`action:${l}`;i.has(d)||(e.push({id:d,type:"action",label:l,stats:{requestCount:c.count,avgLatencyMs:c.count>0?Math.round(c.totalMs/c.count):0,errorRate:0,avgQueryCount:0}}),i.add(d));for(let h of c.endpointKeys){let m=`endpoint:${h}`;if(i.has(m)){let v=`${d} -> ${m}`;r.find(x=>x.id===v)||r.push({id:v,source:d,target:m,type:"triggers",stats:{frequency:c.count,avgLatencyMs:0}});}}}return {nodes:e,edges:r}}function fr(o){let s=new Map;for(let t of o){let e=t.label||"Unknown",r=s.get(e);r||(r={keys:new Set,count:0,totalMs:0},s.set(e,r)),r.count++,r.totalMs+=t.totalDurationMs;for(let i of t.requests)i.path?.startsWith(F)||r.keys.add(ss(i.method,i.path));}return [...s.entries()].map(([t,e])=>({label:t,occurrences:e.count,endpointKeys:e.keys,avgDurationMs:e.count>0?Math.round(e.totalMs/e.count):0}))}function be(o,s){let t=`event=${encodeURIComponent(o)}${s?`&detail=${encodeURIComponent(s)}`:""}`;fetch(`${w.tab}?${t}`).catch(()=>{});}var M=class extends E{constructor(){super(...arguments);this.graphNodes=[];this.graphEdges=[];this.locked=null;this.hovered=null;this.loading=true;this.activeLayers=new Set;this.searchQuery="";this.viewTransform={x:0,y:0,scale:1};this.isPanning=false;this.panStart={x:0,y:0,vtx:0,vty:0};this.dragging=null;this.wasDragging=false;this.nodePositionOverrides=new Map;this.detailTab="overview";this.consolidatedFlows=[];this.activeFlowIdx=-1;this.focusIdx=-1;this.refreshTimer=null;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.loadData(),this.refreshTimer=setInterval(()=>this.loadData(),4e3);}disconnectedCallback(){super.disconnectedCallback(),this.refreshTimer&&clearInterval(this.refreshTimer);}async loadData(){try{let[t,e]=await Promise.all([fetch(`${w.graph}?level=endpoints`),fetch(w.flows)]),r=await t.json(),i=await e.json(),n=mr(r.nodes||[],r.edges||[],i.flows||[]);this.graphNodes=n.nodes,this.graphEdges=n.edges,this.consolidatedFlows=fr(i.flows||[]),this.nodePositionOverrides.size===0&&this.graphNodes.length>0&&this.tryLoadPersistedPositions(),this.loading=!1;}catch{this.loading=false;}}getPositionStorageKey(){let t=this.graphNodes.map(r=>r.id).sort().join(","),e=0;for(let r=0;r<t.length;r++)e=(e<<5)-e+t.charCodeAt(r)|0;return `bk-graph-pos-${e}`}persistPositions(){if(this.nodePositionOverrides.size!==0)try{let t=Object.fromEntries(this.nodePositionOverrides);localStorage.setItem(this.getPositionStorageKey(),JSON.stringify(t));}catch{}}tryLoadPersistedPositions(){try{let t=localStorage.getItem(this.getPositionStorageKey());if(t){let e=JSON.parse(t);this.nodePositionOverrides=new Map(Object.entries(e));}}catch{}}get activeNodeId(){return this.locked??this.hovered}getHighlightedNodeIds(){let t=this.activeNodeId;if(!t)return null;let e=new Set([t]),r=true;for(;r;){r=false;for(let i of this.graphEdges)e.has(i.source)&&!e.has(i.target)&&(e.add(i.target),r=true);}return e}getFlowTraceNodeIds(){if(this.activeFlowIdx<0||this.activeFlowIdx>=this.consolidatedFlows.length)return null;let t=this.consolidatedFlows[this.activeFlowIdx],e=new Set;e.add(`action:${t.label}`);for(let r of t.endpointKeys)e.add(`endpoint:${r}`);for(let r of this.graphEdges)e.has(r.source)&&e.add(r.target);return e}getFlowTraceEdgeIds(){let t=this.getFlowTraceNodeIds();if(!t)return null;let e=new Set;for(let r of this.graphEdges)t.has(r.source)&&t.has(r.target)&&e.add(r.id);return e}matchesSearch(t){return this.searchQuery?t.toLowerCase().includes(this.searchQuery.toLowerCase()):true}handlePanStart(t){t.button===0&&(t.target.closest(".graph-g")||(this.isPanning=true,this.panStart={x:t.clientX,y:t.clientY,vtx:this.viewTransform.x,vty:this.viewTransform.y}));}handlePanMove(t){if(this.dragging){let e=t.currentTarget.getBoundingClientRect(),r=(t.clientX-e.left-this.viewTransform.x)/this.viewTransform.scale,i=(t.clientY-e.top-this.viewTransform.y)/this.viewTransform.scale;this.nodePositionOverrides.set(this.dragging.nodeId,{x:r-this.dragging.offsetX,y:i-this.dragging.offsetY}),this.requestUpdate();return}this.isPanning&&(this.viewTransform={...this.viewTransform,x:this.panStart.vtx+(t.clientX-this.panStart.x),y:this.panStart.vty+(t.clientY-this.panStart.y)});}handlePanEnd(){this.dragging&&(this.persistPositions(),this.dragging=null,this.wasDragging=true,requestAnimationFrame(()=>{this.wasDragging=false;})),this.isPanning=false;}resetView(){this.viewTransform={x:0,y:0,scale:1};}zoomIn(){this.viewTransform={...this.viewTransform,scale:Math.min(nr,this.viewTransform.scale*ts)};}zoomOut(){this.viewTransform={...this.viewTransform,scale:Math.max(or,this.viewTransform.scale/ts)};}resetLayout(){this.nodePositionOverrides.clear();try{localStorage.removeItem(this.getPositionStorageKey());}catch{}this.viewTransform={x:0,y:0,scale:1},this.requestUpdate(),be("layout_reset");}startNodeDrag(t,e,r){t.stopPropagation();let i=t.currentTarget.closest("svg").getBoundingClientRect(),n=(t.clientX-i.left-this.viewTransform.x)/this.viewTransform.scale,l=(t.clientY-i.top-this.viewTransform.y)/this.viewTransform.scale;this.dragging={nodeId:e,offsetX:n-r.x,offsetY:l-r.y};}handleKeyDown(t){let e=this.graphNodes;if(t.key==="/"){t.preventDefault(),this.querySelector(".graph-search-input")?.focus();return}if(t.key==="Escape"){this.locked=null,this.searchQuery="",this.focusIdx=-1,this.activeFlowIdx=-1;return}if(t.key==="Tab"){t.preventDefault(),this.focusIdx=t.shiftKey?this.focusIdx<=0?e.length-1:this.focusIdx-1:(this.focusIdx+1)%e.length,this.hovered=e[this.focusIdx]?.id??null;return}if(t.key==="Enter"&&this.focusIdx>=0){let r=e[this.focusIdx];r&&(this.locked=this.locked===r.id?null:r.id);return}if(t.key==="+"||t.key==="="){this.zoomIn();return}if(t.key==="-"){this.zoomOut();return}if(t.key==="ArrowUp"){this.viewTransform={...this.viewTransform,y:this.viewTransform.y+Kt};return}if(t.key==="ArrowDown"){this.viewTransform={...this.viewTransform,y:this.viewTransform.y-Kt};return}if(t.key==="ArrowLeft"){this.viewTransform={...this.viewTransform,x:this.viewTransform.x+Kt};return}if(t.key==="ArrowRight"){this.viewTransform={...this.viewTransform,x:this.viewTransform.x-Kt};return}}render(){if(this.loading&&this.graphNodes.length===0)return a`<div class="graph-loading">Loading graph…</div>`;if(this.graphNodes.length===0)return a`
734
+ <div class="graph-empty">
735
+ <div class="graph-empty-icon">◎</div>
736
+ <div class="graph-empty-title">No data yet</div>
737
+ <div class="graph-empty-desc">Navigate your app to build the dependency graph.</div>
738
+ </div>
739
+ `;let t=hr(this.graphNodes,this.graphEdges);this.applyPositionOverrides(t);let e=this.getSelectedNodeDetail(),r=this.getHighlightedNodeIds(),i=this.getFlowTraceNodeIds(),n=this.getFlowTraceEdgeIds(),l=this.deduplicateColumnHeaders(t.nodes),c=Math.max(1,...this.graphNodes.map(h=>h.stats.requestCount)),d=this.viewTransform;return a`
740
+ <div class="graph-wrapper" tabindex="0" @keydown=${this.handleKeyDown}
741
+ @click=${h=>{let m=h.target;m.closest(".graph-detail")||m.closest(".graph-toolbar")||m.closest(".graph-float")||m.closest(".graph-g")||(this.locked=null);}}>
742
+ ${this.renderToolbar()}
743
+ <div class="graph-body">
744
+ <div class="graph-canvas" style="position:relative">
745
+ <svg width="100%" height="100%"
746
+ viewBox="0 0 ${Math.max(t.width,ar)} ${Math.max(t.height,lr)}"
747
+ class="graph-svg"
748
+ style="cursor:${this.isPanning?"grabbing":"grab"}"
749
+ @mousedown=${this.handlePanStart}
750
+ @mousemove=${this.handlePanMove}
751
+ @mouseup=${this.handlePanEnd}
752
+ @mouseleave=${this.handlePanEnd}>
753
+
754
+ <g transform="translate(${d.x},${d.y}) scale(${d.scale})">
755
+ ${O`${l.map(h=>O`
756
+ <text x="${h.x}" y="${58}" class="graph-col-header">${h.label}</text>
757
+ `)}`}
758
+
759
+ ${t.edges.map(h=>this.renderEdge(h,r,n,c))}
760
+ ${t.nodes.map(h=>this.renderNode(h,r,i,c))}
761
+ </g>
762
+ </svg>
763
+ ${this.renderFloatingControls()}
764
+ </div>
765
+ ${e?this.renderDetailPanel(e):p}
766
+ </div>
767
+ </div>
768
+ `}applyPositionOverrides(t){for(let r of t.nodes){let i=this.nodePositionOverrides.get(r.id);i&&(r.x=i.x,r.y=i.y);}let e=new Map(t.nodes.map(r=>[r.id,r]));for(let r of t.edges){let i=e.get(r.data.source),n=e.get(r.data.target);if(i&&n){let l=i.x<n.x;r.sx=l?i.x+i.w:i.x,r.sy=i.y+i.h/2,r.tx=l?n.x:n.x+n.w,r.ty=n.y+n.h/2;}}}deduplicateColumnHeaders(t){let e=[],r=new Set;for(let i of t)r.has(i.type)||(r.add(i.type),e.push({x:i.x,label:At[i.type]?.columnHeader||i.type.toUpperCase()}));return e}renderToolbar(){return a`
769
+ <div class="graph-toolbar">
770
+ <div class="graph-layer-toggles">
771
+ ${Object.keys(Xe).map(t=>{let e=Xe[t],r=this.activeLayers.has(t);return a`
772
+ <button class="graph-layer-btn ${r?"active":""}"
773
+ style="${r?`border-color:${e.color};color:${e.color}`:""}"
774
+ @click=${()=>this.toggleLayer(t)}
775
+ title="${e.tooltip}">
776
+ ${e.icon} ${e.label}
777
+ </button>
778
+ `})}
779
+ </div>
780
+
781
+ <div class="graph-search">
782
+ <span class="graph-search-icon">⌕</span>
783
+ <input class="graph-search-input" type="text" placeholder="Search nodes… ( / )"
784
+ .value=${this.searchQuery}
785
+ @input=${t=>{this.searchQuery=t.target.value;}}>
786
+ ${this.searchQuery?a`
787
+ <button class="graph-search-clear" @click=${()=>{this.searchQuery="";}}>✕</button>
788
+ `:p}
789
+ </div>
790
+
791
+ ${this.consolidatedFlows.length>0?a`
792
+ <select class="graph-flow-picker" @change=${t=>{this.activeFlowIdx=parseInt(t.target.value,10),this.activeFlowIdx>=0&&be("flow_traced");}}>
793
+ <option value="-1">Trace flow…</option>
794
+ ${this.consolidatedFlows.map((t,e)=>a`
795
+ <option value="${e}" ?selected=${this.activeFlowIdx===e}>${t.label} → ${t.endpointKeys.size} ep · ${t.occurrences}×</option>
796
+ `)}
797
+ </select>
798
+ `:p}
799
+
800
+ ${this.activeLayers.has("auth")?a`
801
+ <div class="graph-auth-legend">
802
+ <span class="graph-auth-legend-item"><span style="color:${ze}">🛡</span> protected</span>
803
+ <span class="graph-auth-legend-item"><span style="color:${ve};font-weight:700">!</span> no auth</span>
804
+ </div>
805
+ `:p}
806
+ </div>
807
+ `}renderFloatingControls(){let t=this.nodePositionOverrides.size>0,e=Math.round(this.viewTransform.scale*100);return a`
808
+ <div class="graph-float">
809
+ <button class="graph-float-btn" @click=${this.zoomOut} title="Zoom out (-)">−</button>
810
+ <span class="graph-float-zoom">${e}%</span>
811
+ <button class="graph-float-btn" @click=${this.zoomIn} title="Zoom in (+)">+</button>
812
+ <span class="graph-float-sep"></span>
813
+ <button class="graph-float-btn" @click=${this.resetView} title="Reset pan & zoom">⊙</button>
814
+ ${t?a`
815
+ <span class="graph-float-sep"></span>
816
+ <button class="graph-float-btn graph-float-btn-accent" @click=${()=>this.resetLayout()} title="Reset layout to auto-arrange">
817
+ ⟲ Reformat
818
+ </button>
819
+ `:p}
820
+ <span class="graph-float-sep"></span>
821
+ <button class="graph-float-btn" @click=${()=>this.captureScreenshot()} title="Save graph as PNG">
822
+ 📷
823
+ </button>
824
+ </div>
825
+ `}async captureScreenshot(){be("screenshot_captured");let t=this.querySelector(".graph-svg");if(!t)return;let e=t.cloneNode(true);e.setAttribute("xmlns","http://www.w3.org/2000/svg"),e.style.cssText="",e.removeAttribute("class");let r=document.createElement("style");r.textContent=`
826
+ text { font-family: 'Inter', system-ui, -apple-system, sans-serif; }
827
+ .graph-col-header { fill: #c4c4cc; font-size: 9px; font-weight: 600; letter-spacing: 1.5px; }
828
+ .graph-flow-edge { stroke-dasharray: 6,4; }
829
+ .graph-pulse { }
830
+ `,e.insertBefore(r,e.firstChild);let n=document.createElementNS("http://www.w3.org/2000/svg","rect");n.setAttribute("width","100%"),n.setAttribute("height","100%"),n.setAttribute("fill","#ffffff"),e.insertBefore(n,e.firstChild);let l=e.getAttribute("viewBox")||"0 0 800 500",[,,c,d]=l.split(" ").map(Number),h=2,m=c*h,v=d*h,x=new XMLSerializer().serializeToString(e),y=new Blob([x],{type:"image/svg+xml;charset=utf-8"}),k=URL.createObjectURL(y),$=new Image;$.onload=()=>{let f=document.createElement("canvas");f.width=m,f.height=v;let g=f.getContext("2d");g.fillStyle="#ffffff",g.fillRect(0,0,m,v),g.drawImage($,0,0,m,v),URL.revokeObjectURL(k),f.toBlob(T=>{if(!T)return;let R=document.createElement("a");R.href=URL.createObjectURL(T),R.download=`brakit-graph-${new Date().toISOString().slice(0,19).replace(/[T:]/g,"-")}.png`,document.body.appendChild(R),R.click(),document.body.removeChild(R),URL.revokeObjectURL(R.href);},"image/png");},$.src=k;}toggleLayer(t){let e=new Set(this.activeLayers);e.has(t)?e.delete(t):(e.add(t),be("layer_toggled",t)),this.activeLayers=e;}renderNode(t,e,r,i){let n=this.activeNodeId,l=e===null||e.has(t.id),c=n===t.id,d=this.locked===t.id,h=r?.has(t.id)??false,m=this.matchesSearch(t.label),v=At[t.type]||At.endpoint,x=d?zs:c?Zs:v.stroke,y=d?Js:c?tr:v.fill,k=d?2:c?1.5:.75,$=l?1:.08;this.searchQuery&&!m&&($=.05),r&&!h&&($=Math.min($,.08)),h&&($=1,x=Ke);let f=this.searchQuery&&m,g=t.annotations,T=this.activeLayers;T.has("performance")&&g?.p95Ms!==void 0&&t.type==="endpoint"&&(y=It(g.p95Ms)+"18"),T.has("heat")&&(y=Ve(t.stats.requestCount/i)+"20");let R=T.has("auth")&&t.type==="endpoint"&&!g?.hasAuth,H=T.has("auth")&&g?.hasAuth,X=T.has("security")?g?.securityFindings?.length??0:0,B=g?.securityFindings?.some(q=>q.severity==="critical"),V=T.has("issues")?g?.openIssueCount??0:0,G=this.nodeSubtitle(t),C=T.has("performance")&&g?.p95Ms!==void 0&&t.type==="endpoint";return O`
831
+ <g class="graph-g" transform="translate(${t.x},${t.y})" style="opacity:${$};cursor:pointer;transition:opacity .15s,transform .1s"
832
+ @click=${q=>{q.stopPropagation(),!this.wasDragging&&(this.locked=this.locked===t.id?null:t.id,this.detailTab="overview");}}
833
+ @mouseenter=${()=>{this.hovered=t.id;}}
834
+ @mouseleave=${()=>{this.hovered=null;}}
835
+ @mousedown=${q=>{q.detail>=2||this.startNodeDrag(q,t.id,t);}}>
836
+
837
+ ${f?O`
838
+ <rect x="-3" y="-3" width="${t.w+6}" height="${t.h+6}" rx="9" fill="none"
839
+ stroke="${er}" stroke-width="2" stroke-dasharray="4,2"/>
840
+ `:p}
841
+
842
+ ${R?O`
843
+ <rect width="${t.w}" height="${t.h}" rx="8" fill="${y}" stroke="${ve}"
844
+ stroke-width="1.2" stroke-dasharray="5,3"/>
845
+ `:O`
846
+ <rect width="${t.w}" height="${t.h}" rx="8" fill="${y}" stroke="${x}" stroke-width="${k}"/>
847
+ `}
848
+
849
+ <text x="12" y="${t.h/2-4}" fill="#1e293b" font-size="11.5" font-weight="600"
850
+ font-family="'Inter',system-ui,sans-serif">${v.icon} ${t.label}</text>
851
+ <text x="12" y="${t.h/2+10}" fill="#a1a1aa" font-size="9"
852
+ font-family="ui-monospace,monospace">${G}</text>
853
+
854
+ ${C?O`
855
+ <text x="${t.w-8}" y="${t.h-6}" fill="${It(g.p95Ms)}" font-size="9"
856
+ font-family="ui-monospace,monospace" text-anchor="end">p95: ${g.p95Ms}ms</text>
857
+ `:p}
858
+
859
+ ${H?O`
860
+ <g transform="translate(${t.w-24},3)">
861
+ <title>Auth protected</title>
862
+ <rect width="18" height="18" rx="3" fill="${sr}" stroke="${ze}" stroke-width="0.5"/>
863
+ <text x="9" y="13" text-anchor="middle" font-size="10">🛡</text>
864
+ </g>
865
+ `:p}
866
+
867
+ ${R?O`
868
+ <g transform="translate(${t.w-24},3)">
869
+ <title>No auth detected — this endpoint may be unprotected</title>
870
+ <rect width="18" height="18" rx="3" fill="#fff7ed" stroke="${ve}" stroke-width="0.5"/>
871
+ <text x="9" y="13" text-anchor="middle" font-size="10" fill="#ea580c">!</text>
872
+ </g>
873
+ `:p}
874
+
875
+ ${X>0?O`
876
+ <g transform="translate(${t.w-(H||R?46:24)},3)">
877
+ <rect width="18" height="18" rx="3" fill="${B?rr:ir}"
878
+ stroke="${B?Je:Ze}" stroke-width="0.5"
879
+ class="${B?"graph-pulse":""}"/>
880
+ <text x="9" y="13" text-anchor="middle" font-size="9" font-weight="600"
881
+ fill="${B?Je:Ze}">${X}</text>
882
+ </g>
883
+ `:p}
884
+
885
+ ${V>0?O`
886
+ <circle cx="${t.w-8}" cy="8" r="5" fill="${ct}" stroke="white" stroke-width="1"/>
887
+ <text x="${t.w-8}" y="11" text-anchor="middle" font-size="7" fill="white" font-weight="700">${V}</text>
888
+ `:t.stats.errorRate>.05?O`<circle cx="${t.w-12}" cy="12" r="4" fill="${ct}"/>`:p}
889
+
890
+ ${g?.isMiddleware&&T.has("auth")?O`
891
+ <text x="${t.w}" y="${t.h+12}" text-anchor="end" font-size="8" fill="#6b7280"
892
+ font-family="ui-monospace,monospace">middleware</text>
893
+ `:p}
894
+ </g>
895
+ `}nodeSubtitle(t){switch(t.type){case "endpoint":return `${t.stats.requestCount} req \xB7 ${t.stats.avgLatencyMs}ms${t.stats.avgQueryCount>0?` \xB7 ${t.stats.avgQueryCount}q`:""}`;case "action":return `${t.stats.requestCount}\xD7 \xB7 ${t.stats.avgLatencyMs}ms`;case "table":return "table";default:return "service"}}renderEdge(t,e,r,i){let n=this.activeNodeId,l=e===null||e.has(t.data.source)&&e.has(t.data.target),c=r?.has(t.key)??false,d=l?n===null?.25:.6:.04,h=l&&n!==null,m=t.color,v=t.thickness;if(r&&!c&&(d=.04),c&&(d=.85,m=Ke,v=Math.max(v,1.8)),this.activeLayers.has("heat")&&!c){let V=Math.max(1,...this.graphEdges.map(C=>C.stats.frequency)),G=t.data.stats.frequency/V;m=Ve(G),l&&(d=Math.max(d,.4));}let x=this.activeLayers.has("issues")&&t.data.annotations?.hasIssue,y=Math.abs(t.tx-t.sx),k=Math.min(y*.45,120),$=t.sx<t.tx,f=$?t.sx+k:t.sx-k,g=$?t.tx-k:t.tx+k,T=(t.sx+t.tx)/2,R=(t.sy+t.ty)/2,H=4,X=x?ct:m,B=x?Math.max(v,1.5):v;return O`
896
+ <g style="transition:opacity .15s">
897
+ <path d="M${t.sx},${t.sy} C${f},${t.sy} ${g},${t.ty} ${t.tx},${t.ty}"
898
+ fill="none" stroke="${X}" stroke-width="${B}"
899
+ stroke-opacity="${d}" stroke-linecap="round"
900
+ stroke-dasharray="${c?"6,4":t.dashed?"3,3":"none"}"
901
+ class="${c?"graph-flow-edge":""}"/>
902
+ <polygon points="${t.tx},${t.ty} ${t.tx+($?-H*1.5:H*1.5)},${t.ty-H} ${t.tx+($?-H*1.5:H*1.5)},${t.ty+H}"
903
+ fill="${X}" fill-opacity="${d}"/>
904
+ ${h?O`
905
+ <rect x="${T-t.label.length*2.8-2}" y="${R-7}" width="${t.label.length*5.6+8}" height="14"
906
+ rx="4" fill="white" fill-opacity="0.92" stroke="${m}" stroke-width="0.4" stroke-opacity="0.15"/>
907
+ <text x="${T}" y="${R+3.5}" fill="${m}" font-size="8" font-weight="500"
908
+ font-family="ui-monospace,monospace" text-anchor="middle" opacity="0.85">${t.label}</text>
909
+ `:p}
910
+ ${x?O`
911
+ <text x="${T}" y="${R-10}" fill="${ct}" font-size="8" font-weight="600"
912
+ text-anchor="middle">⚠ N+1</text>
913
+ `:p}
914
+ </g>
915
+ `}renderDetailPanel(t){let{node:e,edges:r}=t,i=At[e.type]||At.endpoint,n=e.annotations,l=(n?.securityFindings?.length??0)>0,c=(n?.openIssueCount??0)>0,d=n?.p95Ms!==void 0,m=[{key:"overview",label:"Overview",show:true},{key:"security",label:`Security${l?` (${n.securityFindings.length})`:""}`,show:l},{key:"performance",label:"Perf",show:d},{key:"issues",label:`Issues${c?` (${n.openIssueCount})`:""}`,show:c}].filter(v=>v.show);return a`
916
+ <div class="graph-detail">
917
+ <div class="graph-detail-head">
918
+ <div>
919
+ <div class="graph-detail-badge" style="color:${i.stroke}">${i.icon} ${e.type}</div>
920
+ <div class="graph-detail-name">${e.label}</div>
921
+ ${n?.hasAuth?a`<span class="graph-detail-auth-badge">🛡 Authenticated</span>`:p}
922
+ ${n?.isMiddleware?a`<span class="graph-detail-mw-badge">middleware</span>`:p}
923
+ </div>
924
+ <button class="graph-detail-close" @click=${()=>{this.locked=null;}}>✕</button>
925
+ </div>
926
+
927
+ ${m.length>1?a`
928
+ <div class="graph-detail-tabs">
929
+ ${m.map(v=>a`
930
+ <button class="graph-detail-tab ${this.detailTab===v.key?"active":""}"
931
+ @click=${()=>{this.detailTab=v.key;}}>${v.label}</button>
932
+ `)}
933
+ </div>
934
+ `:p}
935
+
936
+ ${this.detailTab==="overview"?this.renderOverviewTab(e,r):p}
937
+ ${this.detailTab==="security"?this.renderSecurityTab(n):p}
938
+ ${this.detailTab==="performance"?this.renderPerformanceTab(e,n):p}
939
+ ${this.detailTab==="issues"?this.renderIssuesTab(n):p}
940
+ </div>
941
+ `}renderOverviewTab(t,e){return a`
942
+ <div class="graph-detail-stats">
943
+ <div class="graph-detail-stat">
944
+ <div class="graph-detail-val">${t.stats.requestCount}</div>
945
+ <div class="graph-detail-lbl">${t.type==="action"?"OCCURRENCES":"REQUESTS"}</div>
946
+ </div>
947
+ <div class="graph-detail-stat">
948
+ <div class="graph-detail-val" style="color:${It(t.stats.avgLatencyMs)}">${t.stats.avgLatencyMs}ms</div>
949
+ <div class="graph-detail-lbl">AVG LATENCY</div>
950
+ </div>
951
+ ${t.stats.avgQueryCount>0?a`
952
+ <div class="graph-detail-stat">
953
+ <div class="graph-detail-val">${t.stats.avgQueryCount}</div>
954
+ <div class="graph-detail-lbl">QUERIES/REQ</div>
955
+ </div>
956
+ `:p}
957
+ ${t.stats.errorRate>.01?a`
958
+ <div class="graph-detail-stat">
959
+ <div class="graph-detail-val" style="color:${ct}">${Math.round(t.stats.errorRate*100)}%</div>
960
+ <div class="graph-detail-lbl">ERRORS</div>
961
+ </div>
962
+ `:p}
963
+ </div>
964
+
965
+ ${e.length>0?a`
966
+ <div class="graph-detail-sec">Connections</div>
967
+ ${e.map(r=>{let i=r.source===this.locked,n=(i?r.target:r.source).replace(/^(action|endpoint|table|external):/,"");return a`
968
+ <div class="graph-detail-conn">
969
+ <span class="graph-detail-edge-dot" style="background:${fe[r.type]}"></span>
970
+ <span class="graph-detail-edge-type">${r.type}</span>
971
+ <span>${i?"\u2192":"\u2190"} ${n}</span>
972
+ <span class="graph-detail-dim">${r.stats.frequency}× · ${r.stats.avgLatencyMs}ms</span>
973
+ </div>
974
+ `})}
975
+ `:p}
976
+
977
+ ${e.some(r=>r.patterns?.length)?a`
978
+ <div class="graph-detail-sec">SQL Patterns</div>
979
+ ${e.filter(r=>r.patterns).flatMap(r=>r.patterns).map(r=>a`
980
+ <pre class="graph-detail-sql">${r.length>200?r.slice(0,200)+"\u2026":r}</pre>
981
+ `)}
982
+ `:p}
983
+ `}renderSecurityTab(t){return t?.securityFindings?.length?a`
984
+ ${t.securityFindings.map(e=>a`
985
+ <div class="graph-detail-finding">
986
+ <span class="graph-detail-severity graph-detail-severity-${e.severity}">${e.severity}</span>
987
+ <div class="graph-detail-finding-title">${e.title}</div>
988
+ <div class="graph-detail-finding-meta">${e.rule} · ${e.count} occurrence${e.count!==1?"s":""}</div>
989
+ </div>
990
+ `)}
991
+ `:a`<div class="graph-detail-empty">No security findings</div>`}renderPerformanceTab(t,e){return a`
992
+ <div class="graph-detail-stats">
993
+ ${e?.p95Ms!==void 0?a`
994
+ <div class="graph-detail-stat">
995
+ <div class="graph-detail-val" style="color:${It(e.p95Ms)}">${e.p95Ms}ms</div>
996
+ <div class="graph-detail-lbl">P95 LATENCY</div>
997
+ </div>
998
+ `:p}
999
+ <div class="graph-detail-stat">
1000
+ <div class="graph-detail-val" style="color:${It(t.stats.avgLatencyMs)}">${t.stats.avgLatencyMs}ms</div>
1001
+ <div class="graph-detail-lbl">AVG LATENCY</div>
1002
+ </div>
1003
+ ${t.stats.avgQueryCount>0?a`
1004
+ <div class="graph-detail-stat">
1005
+ <div class="graph-detail-val">${t.stats.avgQueryCount}</div>
1006
+ <div class="graph-detail-lbl">QUERIES/REQ</div>
1007
+ </div>
1008
+ `:p}
1009
+ <div class="graph-detail-stat">
1010
+ <div class="graph-detail-val">${t.stats.requestCount}</div>
1011
+ <div class="graph-detail-lbl">TOTAL REQS</div>
1012
+ </div>
1013
+ </div>
1014
+
1015
+ ${(e?.insights?.length??0)>0?a`
1016
+ <div class="graph-detail-sec">Performance Insights</div>
1017
+ ${e.insights.map(r=>a`
1018
+ <div class="graph-detail-finding">
1019
+ <span class="graph-detail-severity graph-detail-severity-${r.severity}">${r.severity}</span>
1020
+ <div class="graph-detail-finding-title">${r.title}</div>
1021
+ <div class="graph-detail-finding-meta">${r.type}</div>
1022
+ </div>
1023
+ `)}
1024
+ `:p}
1025
+ `}renderIssuesTab(t){let e=t?.openIssueCount??0;return e===0?a`<div class="graph-detail-empty">No open issues</div>`:a`
1026
+ <div class="graph-detail-issue-summary">
1027
+ <div class="graph-detail-stat">
1028
+ <div class="graph-detail-val" style="color:${ct}">${e}</div>
1029
+ <div class="graph-detail-lbl">OPEN ISSUES</div>
1030
+ </div>
1031
+ </div>
1032
+ <p class="graph-detail-hint">View the Issues tab for full details and remediation hints.</p>
1033
+ `}getSelectedNodeDetail(){if(!this.locked)return null;let t=this.graphNodes.find(r=>r.id===this.locked);if(!t)return null;let e=this.graphEdges.filter(r=>r.source===this.locked||r.target===this.locked);return {node:t,edges:e}}};u([I({context:A})],M.prototype,"store",2),u([b()],M.prototype,"graphNodes",2),u([b()],M.prototype,"graphEdges",2),u([b()],M.prototype,"locked",2),u([b()],M.prototype,"hovered",2),u([b()],M.prototype,"loading",2),u([b()],M.prototype,"activeLayers",2),u([b()],M.prototype,"searchQuery",2),u([b()],M.prototype,"viewTransform",2),u([b()],M.prototype,"dragging",2),u([b()],M.prototype,"detailTab",2),u([b()],M.prototype,"consolidatedFlows",2),u([b()],M.prototype,"activeFlowIdx",2),u([b()],M.prototype,"focusIdx",2),M=u([S("bk-graph-view")],M);function qi(o){return o===0?"<1ms":_(o)}var N=class extends E{constructor(){super(...arguments);this.requestId="";this.requestStarted=0;this.data=null;this.loading=false;this.failed=false;this.expandedSqlIdx=-1;}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.store.addEventListener("state-changed",()=>this.requestUpdate()),this.requestId&&this.loadTimeline();}async loadTimeline(){if(!this.requestId)return;let t=N.cache.get(this.requestId);if(t){this.data=t;return}this.loading=true;try{let e=await fetch(`${w.activity}?requestId=${this.requestId}`);if(!e.ok){this.failed=!0,this.loading=!1;return}let r=await e.json();if(N.cache.size>=ke){let i=N.cache.keys().next().value;i!==void 0&&N.cache.delete(i);}N.cache.set(this.requestId,r),this.data=r,this.loading=!1;}catch(e){console.debug("[brakit] timeline load failed:",e),this.failed=true,this.loading=false;}}toggleSql(t,e){e.stopPropagation(),this.expandedSqlIdx=this.expandedSqlIdx===t?-1:t;}copySql(t,e){e.stopPropagation(),navigator.clipboard.writeText(t).then(()=>D.show("SQL copied")).catch(()=>D.show("Copy failed"));}render(){if(this.loading)return a`<div class="tl-loading">Loading activity...</div>`;if(this.failed||!this.data||this.data.total===0)return p;let t=this.data,e=t.timeline[0]?.timestamp??0;return a`
734
1034
  <div class="tl-header">
735
1035
  <span class="tl-title">Activity Timeline</span>
736
1036
  <span class="tl-counts">
737
- ${t.counts.queries>0?a`<span class="tl-count tl-count-query">${t.counts.queries} quer${t.counts.queries===1?"y":"ies"}</span>`:d}
738
- ${t.counts.fetches>0?a`<span class="tl-count tl-count-fetch">${t.counts.fetches} fetch${t.counts.fetches===1?"":"es"}</span>`:d}
739
- ${t.counts.logs>0?a`<span class="tl-count tl-count-log">${t.counts.logs} log${t.counts.logs===1?"":"s"}</span>`:d}
740
- ${t.counts.errors>0?a`<span class="tl-count tl-count-error">${t.counts.errors} error${t.counts.errors===1?"":"s"}</span>`:d}
1037
+ ${t.counts.queries>0?a`<span class="tl-count tl-count-query">${t.counts.queries} quer${t.counts.queries===1?"y":"ies"}</span>`:p}
1038
+ ${t.counts.fetches>0?a`<span class="tl-count tl-count-fetch">${t.counts.fetches} fetch${t.counts.fetches===1?"":"es"}</span>`:p}
1039
+ ${t.counts.logs>0?a`<span class="tl-count tl-count-log">${t.counts.logs} log${t.counts.logs===1?"":"s"}</span>`:p}
1040
+ ${t.counts.errors>0?a`<span class="tl-count tl-count-error">${t.counts.errors} error${t.counts.errors===1?"":"s"}</span>`:p}
741
1041
  </span>
742
1042
  </div>
743
- <div class="tl-events">${this.renderTimeline(t.timeline,s)}</div>
744
- `}renderTimeline(t,s){let r=new Map,o=[];for(let l of t){let c=l.type==="query"?l.data.parentFetchId:void 0;if(l.type==="query"&&c){let p=r.get(c);p||(p=[],r.set(c,p)),p.push(l);}else o.push(l);}let n=0;return o.map(l=>{let c=n++,p=l.type==="fetch"?l.data.fetchId:void 0,h=p?r.get(p):void 0;if(h&&h.length>0){let m=h.length;return a`
745
- ${this.renderEvent(l,c,s)}
1043
+ <div class="tl-events">${this.renderTimeline(t.timeline,e)}</div>
1044
+ `}renderTimeline(t,e){let r=new Map,i=[];for(let l of t){let c=l.type==="query"?l.data.parentFetchId:void 0;if(l.type==="query"&&c){let d=r.get(c);d||(d=[],r.set(c,d)),d.push(l);}else i.push(l);}let n=0;return i.map(l=>{let c=n++,d=l.type==="fetch"?l.data.fetchId:void 0,h=d?r.get(d):void 0;if(h&&h.length>0){let m=h.length;return a`
1045
+ ${this.renderEvent(l,c,e)}
746
1046
  <div class="tl-nested">
747
1047
  <span class="tl-nested-label">${m} nested quer${m===1?"y":"ies"}</span>
748
- ${h.map(E=>{let T=n++;return this.renderEvent(E,T,s,true)})}
1048
+ ${h.map(v=>{let x=n++;return this.renderEvent(v,x,e,true)})}
749
1049
  </div>
750
- `}return this.renderEvent(l,c,s)})}renderEvent(t,s,r,o=false){let n=ts[t.type]||"var(--text-dim)",l=es[t.type]||t.type,c="+"+v(Math.round(t.timestamp-r)),p=t.type==="query"?t.data.sql:void 0,h=!!p,m=this.expandedSqlIdx===s;return a`
751
- <div class="tl-event ${h?"tl-clickable":""} ${o?"tl-nested-event":""}"
1050
+ `}return this.renderEvent(l,c,e)})}renderEvent(t,e,r,i=false){let n=Ms[t.type]||"var(--text-dim)",l=Ns[t.type]||t.type,c="+"+_(Math.round(t.timestamp-r)),d=t.type==="query"?t.data.sql:void 0,h=!!d,m=this.expandedSqlIdx===e;return a`
1051
+ <div class="tl-event ${h?"tl-clickable":""} ${i?"tl-nested-event":""}"
752
1052
  style="${h?"":`border-left-color:${n}`}"
753
- @click=${h?E=>this.toggleSql(s,E):d}>
1053
+ @click=${h?v=>this.toggleSql(e,v):p}>
754
1054
  <span class="tl-event-time">${c}</span>
755
1055
  <span class="tl-event-type" style="color:${n}">${l}</span>
756
1056
  ${this.renderEventContent(t)}
757
- ${p?a`
1057
+ ${d?a`
758
1058
  <div class="tl-event-sql ${m?"open":""}">
759
- <button class="tl-sql-copy" @click=${E=>this.copySql(p,E)}>Copy</button>
760
- ${p}
761
- </div>`:d}
762
- </div>
763
- `}renderEventContent(t){switch(t.type){case "fetch":{let s=t.data,r=s.statusCode>=400;return a`
764
- <span class="tl-event-summary">${s.method} ${s.url}</span>
765
- <span class="tl-event-status" style="${r?"color:var(--red)":""}">${s.statusCode}</span>
766
- <span class="tl-event-dur">${v(s.durationMs)}</span>
767
- `}case "query":{let s=t.data,r=(s.normalizedOp||s.operation||"?").toUpperCase(),o=s.table||s.model||"",n=Ft[r]||"var(--text-dim)";return a`
768
- <span class="tl-event-summary"><span style="color:${n};font-weight:600">${r}</span> ${o}</span>
769
- <span class="tl-event-dur">${_r(s.durationMs)}</span>
770
- `}case "log":{let s=t.data,r=Ke[s.level]||"var(--text-dim)";return a`<span class="tl-event-summary"><span style="color:${r}">${s.level.toUpperCase()}</span> ${s.message}</span>`}case "error":{let s=t.data;return a`<span class="tl-event-summary" style="color:var(--red)">${s.name}: ${s.message}</span>`}default:return d}}};w.cache=new Map,u([R({context:x})],w.prototype,"store",2),u([y({attribute:"request-id"})],w.prototype,"requestId",2),u([y({attribute:"request-started",type:Number})],w.prototype,"requestStarted",2),u([_()],w.prototype,"data",2),u([_()],w.prototype,"loading",2),u([_()],w.prototype,"failed",2),u([_()],w.prototype,"expandedSqlIdx",2),w=u([g("bk-timeline-panel")],w);var Wt=class{constructor(e,t){this.host=e;this.store=t;this.retryCount=0;e.addController(this);}hostConnected(){this.connect();}hostDisconnected(){this.eventSource?.close(),clearTimeout(this.reloadTimer),clearTimeout(this.perfReloadTimer),clearTimeout(this.reconnectTimer);}connect(){this.eventSource?.close(),this.eventSource=new EventSource($.events),this.eventSource.onopen=()=>{this.retryCount=0;},this.eventSource.onerror=()=>{this.eventSource?.close(),this.scheduleReconnect();},this.eventSource.onmessage=e=>{let t=JSON.parse(e.data);t.path?.startsWith(N)||(this.store.prependRequest(t),clearTimeout(this.reloadTimer),this.reloadTimer=setTimeout(()=>this.reloadFlows(),300),this.store.state.activeView==="performance"&&(clearTimeout(this.perfReloadTimer),this.perfReloadTimer=setTimeout(()=>this.reloadMetrics(),ue)));},this.eventSource.addEventListener(ee,e=>{this.store.prependFetch(JSON.parse(e.data));}),this.eventSource.addEventListener("log",e=>{this.store.prependLog(JSON.parse(e.data));}),this.eventSource.addEventListener(se,e=>{this.store.prependError(JSON.parse(e.data));}),this.eventSource.addEventListener(re,e=>{this.store.prependQuery(JSON.parse(e.data));}),this.eventSource.addEventListener(oe,e=>{this.store.setIssues(JSON.parse(e.data));});}scheduleReconnect(){if(this.retryCount>=10)return;let e=Math.min(1e3*2**this.retryCount,3e4);this.retryCount++,this.reconnectTimer=setTimeout(()=>this.connect(),e);}async reloadFlows(){try{let t=await(await fetch($.flows)).json();this.store.setFlows(t.flows);}catch{}}async reloadMetrics(){try{let t=await(await fetch($.metricsLive)).json();this.store.setMetrics(t.endpoints||[]);}catch{}}};function gs(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>`}function Es(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>`}function bs(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>`}function _s(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>`}function Ss(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>`}function Ts(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`}function $s(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>`}function ys(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>`}function xs(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>`}var X=class extends f{constructor(){super(...arguments);this.store=new Gt;this.activeView="overview";this.viewMode="simple";this.sse=new Wt(this,this.store);}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.loadInitialData(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}async loadInitialData(){try{let[t,s]=await Promise.all([fetch($.flows),fetch($.requests)]),[r,o]=await Promise.all([t.json(),s.json()]);this.store.setFlows(r.flows),this.store.setRequests(o.requests);}catch(t){console.warn("[brakit]",t);}try{let[t,s,r,o,n]=await Promise.all([fetch($.fetches),fetch($.errors),fetch($.logs),fetch($.queries),fetch($.metricsLive)]),[l,c,p,h,m]=await Promise.all([t.json(),s.json(),r.json(),o.json(),n.json()]);this.store.setFetches(l.entries),this.store.setErrors(c.entries),this.store.setLogs(p.entries),this.store.setQueries(h.entries),this.store.setMetrics(m.endpoints||[]);}catch(t){console.warn("[brakit]",t);}try{let s=await(await fetch($.insights)).json();this.store.setIssues(s.issues||[]);}catch(t){console.warn("[brakit]",t);}}switchView(t){t!==this.activeView&&(this.activeView=t,this.store.setActiveView(t),fetch(`${$.tab}?tab=${encodeURIComponent(t)}`).catch(()=>{}),t==="performance"&&this.sse.reloadMetrics());}async handleClear(){confirm("This will clear all data including performance metrics history. Continue?")&&(await fetch($.clear,{method:"POST"}),this.store.clearAll(),C.show("Cleared"));}handleCopyAsCurl(t){ct(t);}render(){let t=this.store.state,s=t.requests.filter(c=>!c.path?.startsWith(N)),r=s.filter(c=>c.statusCode>=400).length,o=s.length>0?Math.round(s.reduce((c,p)=>c+p.durationMs,0)/s.length):0,n=(t.issues||[]).filter(c=>c.state!=="resolved"&&c.state!=="stale").length,l=window.__BRAKIT_CONFIG__;return a`
1059
+ <button class="tl-sql-copy" @click=${v=>this.copySql(d,v)}>Copy</button>
1060
+ ${d}
1061
+ </div>`:p}
1062
+ </div>
1063
+ `}renderEventContent(t){switch(t.type){case "fetch":{let e=t.data,r=e.statusCode>=400;return a`
1064
+ <span class="tl-event-summary">${e.method} ${e.url}</span>
1065
+ <span class="tl-event-status" style="${r?"color:var(--red)":""}">${e.statusCode}</span>
1066
+ <span class="tl-event-dur">${_(e.durationMs)}</span>
1067
+ `}case "query":{let e=t.data,r=(e.normalizedOp||e.operation||"?").toUpperCase(),i=e.table||e.model||"",n=pe[r]||"var(--text-dim)";return a`
1068
+ <span class="tl-event-summary"><span style="color:${n};font-weight:600">${r}</span> ${i}</span>
1069
+ <span class="tl-event-dur">${qi(e.durationMs)}</span>
1070
+ `}case "log":{let e=t.data,r=As[e.level]||"var(--text-dim)";return a`<span class="tl-event-summary"><span style="color:${r}">${e.level.toUpperCase()}</span> ${e.message}</span>`}case "error":{let e=t.data;return a`<span class="tl-event-summary" style="color:var(--red)">${e.name}: ${e.message}</span>`}default:return p}}};N.cache=new Map,u([I({context:A})],N.prototype,"store",2),u([L({attribute:"request-id"})],N.prototype,"requestId",2),u([L({attribute:"request-started",type:Number})],N.prototype,"requestStarted",2),u([b()],N.prototype,"data",2),u([b()],N.prototype,"loading",2),u([b()],N.prototype,"failed",2),u([b()],N.prototype,"expandedSqlIdx",2),N=u([S("bk-timeline-panel")],N);function Lt(o){try{return JSON.parse(o)}catch{return null}}var Ee=class{constructor(s,t){this.host=s;this.store=t;this.retryCount=0;this.boundHandlers={fetch:s=>{let t=Lt(s.data);t&&this.store.prependFetch(t);},log:s=>{let t=Lt(s.data);t&&this.store.prependLog(t);},error:s=>{let t=Lt(s.data);t&&this.store.prependError(t);},query:s=>{let t=Lt(s.data);t&&this.store.prependQuery(t);},issues:s=>{let t=Lt(s.data);t&&this.store.setIssues(t);}};s.addController(this);}hostConnected(){this.connect();}hostDisconnected(){this.removeListeners(),this.eventSource?.close(),clearTimeout(this.reloadTimer),clearTimeout(this.perfReloadTimer),clearTimeout(this.reconnectTimer);}removeListeners(){this.eventSource&&(this.eventSource.removeEventListener(ie,this.boundHandlers.fetch),this.eventSource.removeEventListener("log",this.boundHandlers.log),this.eventSource.removeEventListener(oe,this.boundHandlers.error),this.eventSource.removeEventListener(ne,this.boundHandlers.query),this.eventSource.removeEventListener(ae,this.boundHandlers.issues));}connect(){this.removeListeners(),this.eventSource?.close(),this.eventSource=new EventSource(w.events),this.eventSource.onopen=()=>{this.retryCount=0;},this.eventSource.onerror=()=>{this.eventSource?.close(),this.scheduleReconnect();},this.eventSource.onmessage=s=>{let t=Lt(s.data);t&&(t.path?.startsWith(F)||(this.store.prependRequest(t),clearTimeout(this.reloadTimer),this.reloadTimer=setTimeout(()=>this.reloadFlows(),300),this.store.state.activeView==="performance"&&(clearTimeout(this.perfReloadTimer),this.perfReloadTimer=setTimeout(()=>this.reloadMetrics(),De))));},this.eventSource.addEventListener(ie,this.boundHandlers.fetch),this.eventSource.addEventListener("log",this.boundHandlers.log),this.eventSource.addEventListener(oe,this.boundHandlers.error),this.eventSource.addEventListener(ne,this.boundHandlers.query),this.eventSource.addEventListener(ae,this.boundHandlers.issues);}scheduleReconnect(){if(this.retryCount>=10)return;let s=Math.min(1e3*2**this.retryCount,3e4);this.retryCount++,this.reconnectTimer=setTimeout(()=>this.connect(),s);}async reloadFlows(){try{let t=await(await fetch(w.flows)).json();this.store.setFlows(t.flows);}catch{}}async reloadMetrics(){try{let t=await(await fetch(w.metricsLive)).json();this.store.setMetrics(t.endpoints||[]);}catch{}}};function vr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>`}function gr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>`}function br(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>`}function Er(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>`}function yr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>`}function _r(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`}function $r(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>`}function xr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>`}function Sr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>`}function Tr(){return a`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="3"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="18" r="3"/><line x1="9" y1="6" x2="15" y2="6"/><line x1="6" y1="9" x2="6" y2="15"/><line x1="18" y1="9" x2="18" y2="15"/><line x1="9" y1="18" x2="15" y2="18"/></svg>`}var dt=class extends E{constructor(){super(...arguments);this.store=new ue;this.activeView="overview";this.viewMode="simple";this.sse=new Ee(this,this.store);}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.loadInitialData(),this.store.addEventListener("state-changed",()=>this.requestUpdate());}async loadInitialData(){try{let[t,e]=await Promise.all([fetch(w.flows),fetch(w.requests)]),[r,i]=await Promise.all([t.json(),e.json()]);this.store.setFlows(r.flows),this.store.setRequests(i.requests);}catch(t){console.warn("[brakit]",t);}try{let[t,e,r,i,n]=await Promise.all([fetch(w.fetches),fetch(w.errors),fetch(w.logs),fetch(w.queries),fetch(w.metricsLive)]),[l,c,d,h,m]=await Promise.all([t.json(),e.json(),r.json(),i.json(),n.json()]);this.store.setFetches(l.entries),this.store.setErrors(c.entries),this.store.setLogs(d.entries),this.store.setQueries(h.entries),this.store.setMetrics(m.endpoints||[]);}catch(t){console.warn("[brakit]",t);}try{let e=await(await fetch(w.insights)).json();this.store.setIssues(e.issues||[]);}catch(t){console.warn("[brakit]",t);}}switchView(t){t!==this.activeView&&(this.activeView=t,this.store.setActiveView(t),fetch(`${w.tab}?tab=${encodeURIComponent(t)}`).catch(()=>{}),t==="performance"&&this.sse.reloadMetrics());}async handleClear(){confirm("This will clear all data including performance metrics history. Continue?")&&(await fetch(w.clear,{method:"POST"}),this.store.clearAll(),D.show("Cleared"));}handleCopyAsCurl(t){Tt(t);}render(){let t=this.store.state,e=t.requests.filter(c=>!c.path?.startsWith(F)),r=e.filter(c=>c.statusCode>=400).length,i=e.length>0?Math.round(e.reduce((c,d)=>c+d.durationMs,0)/e.length):0,n=(t.issues||[]).filter(c=>c.state!=="resolved"&&c.state!=="stale").length,l=window.__BRAKIT_CONFIG__;return a`
771
1071
  <div class="app" id="app">
772
1072
  <aside class="sidebar">
773
1073
  <div class="sidebar-logo">
@@ -775,25 +1075,31 @@
775
1075
  <span class="logo-version">v${l?.version??""}</span>
776
1076
  </div>
777
1077
  <nav class="sidebar-nav">
778
- ${this.renderSidebarItem("overview","Overview",gs(),void 0)}
1078
+ ${this.renderSidebarItem("overview","Overview",vr(),void 0)}
779
1079
  <div class="sidebar-section">Monitor</div>
780
- ${this.renderSidebarItem("actions","Actions",Es(),t.flows.length)}
781
- ${this.renderSidebarItem("requests","Requests",bs(),s.length)}
782
- ${this.renderSidebarItem("fetches","Fetches",_s(),t.fetches.length)}
1080
+ ${this.renderSidebarItem("actions","Actions",gr(),t.flows.length)}
1081
+ ${this.renderSidebarItem("requests","Requests",br(),e.length)}
1082
+ ${this.renderSidebarItem("fetches","Fetches",Er(),t.fetches.length)}
783
1083
  <div class="sidebar-section">Insights</div>
784
- ${this.renderSidebarItem("queries","Queries",Ss(),t.queries.length)}
785
- ${this.renderSidebarItem("errors","Errors",Ts(),t.errors.length)}
786
- ${this.renderSidebarItem("logs","Logs",$s(),t.logs.length)}
787
- ${this.renderSidebarItem("security","Security",ys(),n,n===0)}
788
- ${this.renderSidebarItem("performance","Performance",xs(),void 0)}
1084
+ ${this.renderSidebarItem("queries","Queries",yr(),t.queries.length)}
1085
+ ${this.renderSidebarItem("errors","Errors",_r(),t.errors.length)}
1086
+ ${this.renderSidebarItem("logs","Logs",$r(),t.logs.length)}
1087
+ ${this.renderSidebarItem("security","Security",xr(),n,n===0)}
1088
+ ${this.renderSidebarItem("performance","Performance",Sr(),void 0)}
1089
+ <div class="sidebar-section">Topology</div>
1090
+ <button class="sidebar-item ${this.activeView==="graph"?"active":""}" @click=${()=>this.switchView("graph")}>
1091
+ <span class="item-icon">${Tr()}</span>
1092
+ <span class="item-label">Graph</span>
1093
+ <span class="sidebar-beta">beta</span>
1094
+ </button>
789
1095
  </nav>
790
1096
  <div class="sidebar-footer">:${l?.port??""}</div>
791
1097
  </aside>
792
1098
  <div class="main-panel">
793
1099
  <div class="header">
794
1100
  <div class="header-left">
795
- <span class="header-title" id="header-title">${ie[this.activeView]||this.activeView}</span>
796
- <span class="header-sub" id="header-sub">${ne[this.activeView]||""}</span>
1101
+ <span class="header-title" id="header-title">${Ie[this.activeView]||this.activeView}</span>
1102
+ <span class="header-sub" id="header-sub">${Ce[this.activeView]||""}</span>
797
1103
  </div>
798
1104
  <div class="header-right">
799
1105
  ${this.activeView==="actions"?a`
@@ -801,7 +1107,7 @@
801
1107
  <button class="segmented-btn ${this.viewMode==="simple"?"active":""}" @click=${()=>{this.viewMode="simple",this.store.setViewMode("simple");}}>Quick</button>
802
1108
  <button class="segmented-btn ${this.viewMode==="detailed"?"active":""}" @click=${()=>{this.viewMode="detailed",this.store.setViewMode("detailed");}}>Detailed</button>
803
1109
  </div>
804
- `:d}
1110
+ `:p}
805
1111
  <button class="btn btn-danger" @click=${this.handleClear}>Clear</button>
806
1112
  </div>
807
1113
  </div>
@@ -833,23 +1139,26 @@
833
1139
  <div class="view-telemetry" id="performance-container" style="display:${this.activeView==="performance"?"block":"none"}">
834
1140
  <bk-performance-view></bk-performance-view>
835
1141
  </div>
1142
+ <div class="view-telemetry" id="graph-container" style="display:${this.activeView==="graph"?"block":"none"}">
1143
+ <bk-graph-view></bk-graph-view>
1144
+ </div>
836
1145
  </div>
837
1146
  <div class="footer">
838
- <span id="stat-total">${s.length} request${s.length!==1?"s":""}</span>
1147
+ <span id="stat-total">${e.length} request${e.length!==1?"s":""}</span>
839
1148
  <span id="stat-flows">${t.flows.length} action${t.flows.length!==1?"s":""}</span>
840
1149
  <span id="stat-errors" class="error-count">${r} error${r!==1?"s":""}</span>
841
- <span id="stat-avg">Avg: ${o}ms</span>
1150
+ <span id="stat-avg">Avg: ${i}ms</span>
842
1151
  </div>
843
1152
  </div>
844
1153
  </div>
845
1154
  <bk-toast></bk-toast>
846
- `}renderSidebarItem(t,s,r,o,n=false){return a`
1155
+ `}renderSidebarItem(t,e,r,i,n=false){return a`
847
1156
  <button class="sidebar-item ${this.activeView===t?"active":""}" @click=${()=>this.switchView(t)}>
848
1157
  <span class="item-icon">${r}</span>
849
- <span class="item-label">${s}</span>
850
- ${o!==void 0?a`<span class="item-count" style="display:${n?"none":""}">${o}</span>`:d}
1158
+ <span class="item-label">${e}</span>
1159
+ ${i!==void 0?a`<span class="item-count" style="display:${n?"none":""}">${i}</span>`:p}
851
1160
  </button>
852
- `}};u([Ee({context:x})],X.prototype,"store",2),u([_()],X.prototype,"activeView",2),u([_()],X.prototype,"viewMode",2),X=u([g("bk-dashboard")],X);
1161
+ `}};u([Be({context:A})],dt.prototype,"store",2),u([b()],dt.prototype,"activeView",2),u([b()],dt.prototype,"viewMode",2),dt=u([S("bk-dashboard")],dt);
853
1162
  /*! Bundled license information:
854
1163
 
855
1164
  @lit/reactive-element/css-tag.js:
@@ -872,6 +1181,8 @@ lit-element/lit-element.js:
872
1181
  @lit/reactive-element/decorators/query-async.js:
873
1182
  @lit/reactive-element/decorators/query-assigned-nodes.js:
874
1183
  @lit/context/lib/decorators/provide.js:
1184
+ lit-html/directive.js:
1185
+ lit-html/directives/unsafe-html.js:
875
1186
  (**
876
1187
  * @license
877
1188
  * Copyright 2017 Google LLC