apitestcenter 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD-PARTY-NOTICES-UI.txt +1 -1
- package/dist/THIRD-PARTY-NOTICES.txt +336 -1
- package/dist/cli.mjs +20969 -1746
- package/dist/ui/404/index.html +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/__next.__PAGE__.txt +10 -10
- package/dist/ui/__next._full.txt +11 -11
- package/dist/ui/__next._tree.txt +2 -2
- package/dist/ui/_next/static/chunks/0-898cb98enjv.css +3 -0
- package/dist/ui/_next/static/chunks/02myfb0nlri-z.js +119 -0
- package/dist/ui/_next/static/chunks/0kfr8kv4cj_kv.js +1 -0
- package/dist/ui/_next/static/chunks/{12eajgls1n2zi.js → 0txpfp028djv6.js} +71 -71
- package/dist/ui/_next/static/chunks/0vkcbl8nakdh1.js +2 -0
- package/dist/ui/_next/static/chunks/13nvl7bxr0ra-.js +1 -0
- package/dist/ui/_next/static/chunks/1w_q4qvvuinj2.js +1 -0
- package/dist/ui/_next/static/chunks/{065oy54s0-cwr.js → 2idsynwg5lkk7.js} +2 -2
- package/dist/ui/_next/static/chunks/{0mlyz754peers.js → 2lw9bsrnh8k4u.js} +1 -1
- package/dist/ui/_next/static/chunks/2nxnxp6p-40kg.js +1 -0
- package/dist/ui/_next/static/chunks/3ad2zh-p8_xhv.js +59 -0
- package/dist/ui/_not-found/__next._full.txt +10 -10
- package/dist/ui/_not-found/__next._not-found.__PAGE__.txt +9 -9
- package/dist/ui/_not-found/__next._tree.txt +2 -2
- package/dist/ui/_not-found/index.html +1 -1
- package/dist/ui/_not-found/index.txt +10 -10
- package/dist/ui/compare/__next._full.txt +11 -11
- package/dist/ui/compare/__next._tree.txt +2 -2
- package/dist/ui/compare/__next.compare.__PAGE__.txt +10 -10
- package/dist/ui/compare/index.html +1 -1
- package/dist/ui/compare/index.txt +11 -11
- package/dist/ui/history/__next._full.txt +12 -12
- package/dist/ui/history/__next._tree.txt +2 -2
- package/dist/ui/history/__next.history.__PAGE__.txt +11 -11
- package/dist/ui/history/index.html +1 -1
- package/dist/ui/history/index.txt +12 -12
- package/dist/ui/index.html +1 -1
- package/dist/ui/index.txt +11 -11
- package/dist/ui/preview/__next._full.txt +12 -12
- package/dist/ui/preview/__next._tree.txt +2 -2
- package/dist/ui/preview/__next.preview.__PAGE__.txt +11 -11
- package/dist/ui/preview/index.html +1 -1
- package/dist/ui/preview/index.txt +12 -12
- package/dist/ui/suite/__next._full.txt +11 -11
- package/dist/ui/suite/__next._tree.txt +2 -2
- package/dist/ui/suite/__next.suite.__PAGE__.txt +10 -10
- package/dist/ui/suite/index.html +1 -1
- package/dist/ui/suite/index.txt +11 -11
- package/dist/ui/tests/__next._full.txt +10 -10
- package/dist/ui/tests/__next._tree.txt +2 -2
- package/dist/ui/tests/__next.tests.__PAGE__.txt +9 -9
- package/dist/ui/tests/index.html +1 -1
- package/dist/ui/tests/index.txt +10 -10
- package/package.json +1 -1
- package/dist/ui/_next/static/chunks/03vwb47zropf0.js +0 -1
- package/dist/ui/_next/static/chunks/0dscs2dqej_33.css +0 -3
- package/dist/ui/_next/static/chunks/0kfnlqyz56lid.js +0 -2
- package/dist/ui/_next/static/chunks/117zwf3ps9-d0.js +0 -1
- package/dist/ui/_next/static/chunks/13hazp8hyksry.js +0 -59
- package/dist/ui/_next/static/chunks/1s74dc_u9f8bv.js +0 -1
- package/dist/ui/_next/static/chunks/1tpf12evb0w6s.js +0 -1
- package/dist/ui/_next/static/chunks/202n35227m-qn.js +0 -119
- /package/dist/ui/_next/static/{nzVJlcyPooozLLxcLfxub → lBYayPKoT6YJhgfHFuw6O}/_buildManifest.js +0 -0
- /package/dist/ui/_next/static/{nzVJlcyPooozLLxcLfxub → lBYayPKoT6YJhgfHFuw6O}/_clientMiddlewareManifest.js +0 -0
- /package/dist/ui/_next/static/{nzVJlcyPooozLLxcLfxub → lBYayPKoT6YJhgfHFuw6O}/_ssgManifest.js +0 -0
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
48
48
|
${u}
|
|
49
49
|
<Relationship Id="rId${c.length+1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
|
50
|
-
</Relationships>`,"xl/styles.xml":k};for(let e of c)x[`xl/worksheets/sheet${e.id}.xml`]=e.xml;return new Blob([(0,w.zipStore)(x)],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})}async function S(e,t,s){let a=N().replace(/\.xlsx$/,""),r={[`${a}.xlsx`]:new Uint8Array(await (await I(e,t,s)).arrayBuffer()),[`${a}.json`]:(0,b.exportCompareJson)(e,t)};for(let t of e){if(!t.probe)continue;let e=t.title.replace(/[^\w.-]+/g,"-").slice(0,40)||t.id.slice(0,8);r[`${e}-probe.json`]=(0,b.exportProbeJson)(t.probe)}return{base:a,blob:(0,w.zipStore)(r)}}var C=e.i(15060),$=e.i(88153);function A({apis:e,mode:s,probes:a}){var n,l,i;let o,d,c,p,m,{slo:u}=(0,$.useSlo)(),x=N(),v=x.replace(/\.xlsx$/,""),j=Object.entries(a).filter(e=>!!e[1]),[k,F]=(0,h.useState)(!1),[R,E]=(0,h.useState)(null),[T,z]=(0,h.useState)(null);if(0===e.length)return null;let D=(n=e,l=s,i=u,o=n.map(e=>e.title),d=`Compare: ${o.join(" vs ")}`.slice(0,120),c=n.length>=2?(0,f.compareKpis)(n.map(e=>e.report)):[],p=[`APITestCenter compare (${l})`,"",...n.map(e=>`- ${e.title}: ${e.report.testName} [${e.report.status}]`),"",...c.map(e=>{let t=e.values.map((t,s)=>{var a,r;return`${o[s]}=${a=t,"ms"===(r=e.unit)?`${Math.round(a)}ms`:"rps"===r?`${a.toFixed(1)}/s`:"pct"===r?`${(100*a).toFixed(2)}%`:String(Math.round(a))}`}).join(", "),s=null==e.winner?"tie":o[e.winner]??"tie";return`${e.label}: ${t} (best: ${s})`})],i&&p.push("",`Performance targets: p95 ${i.p95Ms} ms, errors ${(100*i.errorRate).toFixed(1)}%`),p.push("","Attach the Excel or Zip export from APITestCenter."),{subject:d,body:m=p.join("\n"),mailto:`mailto:?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,gmail:`https://mail.google.com/mail/?view=cm&fs=1&tf=1&su=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,outlook:`https://outlook.office.com/mail/deeplink/compose?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`});async function O(){z(null),F(!1);try{let{base:t,blob:a}=await S(e,s,u),r={files:[new File([a],`${t}-export.zip`,{type:"application/zip"})],title:D.subject,text:D.body};if(navigator.canShare?.({files:r.files}))return void await navigator.share(r);E("mailto")}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;E("mailto"),z(e instanceof Error?e.message:"Share failed")}}return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("span",{className:"mr-1 flex items-center gap-1.5 text-xs text-mute",children:[(0,t.jsx)(g.Download,{size:14}),"Export"]}),(0,t.jsx)("button",{type:"button",disabled:e.length<2,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>void I(e,s,u).then(e=>(0,C.downloadBlob)(x,e)),children:"Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>(0,C.downloadText)(`${v}.json`,(0,b.exportCompareJson)(e,s),"application/json"),children:"JSON"}),(0,t.jsx)("button",{type:"button",disabled:0===j.length,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>{let t={};for(let[s,a]of j){let r=e.find(e=>e.id===s),n=(r?.title??s).replace(/[^\w.-]+/g,"-").slice(0,40);t[`${n}-probe.json`]=(0,b.exportProbeJson)(a)}(0,C.downloadBlob)(`${v}-probes.zip`,(0,w.zipStore)(t))},children:"Response JSONs"}),(0,t.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>void S(e,s,u).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:[(0,t.jsx)(g.Download,{size:12}),"Zip"]}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>F(e=>!e),className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",children:[(0,t.jsx)(y.Share2,{size:12}),"Share",(0,t.jsx)(r.ChevronDown,{size:12})]}),k?(0,t.jsxs)("div",{className:"absolute right-0 z-20 mt-1 w-56 rounded-md border border-line bg-panel p-1 shadow-lg",children:[(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("gmail")},children:"Gmail"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("outlook")},children:"Outlook on the web"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("mailto")},children:"Default mail app"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>void O(),children:"System share"})]}):null]})]}),T?(0,t.jsx)("p",{className:"max-w-md text-xs text-mute",children:T}):null,R?(0,t.jsx)(P,{apis:e,mode:s,target:R,links:D,onClose:()=>E(null)}):null]})}function P({apis:e,mode:s,target:a,links:r,onClose:n}){let{slo:l}=(0,$.useSlo)(),i={gmail:"Gmail",outlook:"Outlook on the web",mailto:"default mail app"},o="gmail"===a?r.gmail:"outlook"===a?r.outlook:r.mailto;return(0,t.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-canvas/70 p-4",role:"presentation",onClick:n,children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true",className:"w-full max-w-md rounded-lg border border-line bg-panel p-4 shadow-xl",onClick:e=>e.stopPropagation(),children:[(0,t.jsxs)("h2",{className:"text-sm font-medium text-ink",children:["Share via ",i[a]]}),(0,t.jsx)("p",{className:"mt-2 text-xs leading-5 text-mute",children:"Download the compare package, then attach it in the compose window. Browsers cannot attach files for you."}),(0,t.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void I(e,s,l).then(e=>(0,C.downloadBlob)(N(),e)),children:"Download Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void S(e,s,l).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:"Download Zip"}),(0,t.jsxs)("a",{href:o,target:"_blank",rel:"noreferrer",className:"rounded-md bg-accent px-2.5 py-1.5 text-xs font-medium text-canvas",onClick:n,children:["Open ",i[a]]}),(0,t.jsx)("button",{type:"button",className:"rounded-md px-2.5 py-1.5 text-xs text-mute",onClick:n,children:"Close"})]})]})})}var F=e.i(55658),R=e.i(53012),E=e.i(45404),T=e.i(29724),z=e.i(88231);function D({items:e,liveTabs:s,running:a,source:r,mode:l,slo:i,title:o,actions:d,status:c,exportBar:p}){let[m,u]=(0,h.useState)("all"),x=(0,h.useRef)(null),b=e.map((e,t)=>(0,f.compareSeriesLabel)(t,e.title)),g=a||!e.some(e=>e.tabId===m)?"all":m,y=e.filter(e=>!s.has(e.tabId)),v=!a&&y.length>=2?(0,F.compareFairness)(y.map(e=>e.report),y.map(t=>b[e.indexOf(t)])):null;return(0,t.jsxs)("div",{ref:x,className:"min-h-0 flex-1 overflow-y-auto",children:[(0,t.jsxs)("header",{className:"sticky top-0 z-10 border-b border-line bg-canvas/95 px-4 pt-3 backdrop-blur lg:px-6",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[(0,t.jsx)("h2",{className:"text-base font-medium text-ink",children:o}),(0,t.jsx)("div",{className:"ml-auto flex flex-wrap items-center gap-2",children:d})]}),(0,t.jsx)("div",{role:"tablist","aria-label":"Comparison or one run",className:"-mb-px mt-3 flex gap-1 overflow-x-auto",children:[{id:"all",label:"Comparison",color:null},...e.map((e,t)=>({id:e.tabId,label:b[t],color:(0,z.seriesColor)(t)}))].map(e=>{let r=g===e.id,l=s.has(e.id);return(0,t.jsxs)("button",{type:"button",role:"tab","aria-selected":r,disabled:a&&"all"!==e.id,title:a&&"all"!==e.id?"Each run's own report opens when the compare has finished":e.label,onClick:()=>{u(e.id),x.current?.scrollTo({top:0})},className:`flex max-w-[18rem] shrink-0 items-center gap-2 rounded-t-md border border-b-0 px-3 py-2 text-sm disabled:opacity-50 ${r?"border-line bg-panel font-medium text-ink":"border-transparent text-mute hover:bg-panel-2 hover:text-ink"}`,children:[e.color?(0,t.jsx)("span",{className:"h-2 w-2 shrink-0 rounded-full",style:{background:e.color},"aria-hidden":!0}):null,(0,t.jsx)("span",{className:"truncate",children:e.label}),l?(0,t.jsx)(n.Loader2,{size:12,className:"shrink-0 animate-spin text-accent","aria-label":"running"}):null]},e.id)})})]}),(0,t.jsx)("div",{className:"space-y-4 px-4 py-4 lg:px-6",children:"all"===g?(0,t.jsxs)(t.Fragment,{children:[c,p,v?.unfair?(0,t.jsxs)("p",{role:"note",className:"flex items-start gap-2 rounded-md border border-warn/40 bg-warn/10 px-3 py-2 text-sm text-ink",children:[(0,t.jsx)(R.AlertTriangle,{size:16,className:"mt-0.5 shrink-0 text-warn","aria-hidden":!0}),(0,t.jsxs)("span",{children:[v.unfair," Compare runs with the same load and length to say which API is faster."]})]}):null,(0,t.jsxs)("p",{className:"text-xs text-mute",children:["saved"===r?`Saved runs: ${e.map((e,t)=>{let s;return`${b[t]} ${Number.isNaN((s=new Date(e.report.startedAt)).getTime())?"":s.toLocaleString(void 0,{day:"numeric",month:"short",hour:"numeric",minute:"2-digit"})}`}).join(" · ")}.`:"parallel"===l?"Ran at the same time — the runs shared this computer's CPU and network, so treat the numbers as directional.":"Ran one after another with the same load.",v&&!v.unfair&&v.caveats.length?` Note: ${v.caveats.join("; ")}.`:""]}),e.length>=2?(0,t.jsx)(E.Dashboard,{scope:"compare",data:{reports:e.map(e=>e.report),titles:e.map((e,t)=>b[t]+(s.has(e.tabId)?" · live":"")),slo:i,live:a}}):(0,t.jsx)("p",{className:"rounded-lg border border-dashed border-line px-6 py-14 text-center text-sm text-mute",children:a?"The overlay appears when the first API is under way…":"The overlay needs at least two finished runs."})]}):(0,t.jsx)(T.ReportView,{report:e.find(e=>e.tabId===g).report,source:"engine"})})]})}var O=e.i(2385),q=e.i(19656);function L(e){let t=Math.max(0,Math.ceil(e/1e3)),s=Math.floor(t/60),a=t%60;return s>0?`${s}:${String(a).padStart(2,"0")}`:`${a}s`}function M(e){let t=Math.max(0,Math.round(e/1e3));if(t<60)return`${t}s`;let s=Math.floor(t/60),a=t%60;return a?`${s}m ${a}s`:`${s}m`}function U({mode:e,phase:s,liveRuns:a,startedAt:r,endedAt:n}){let[l,i]=(0,h.useState)(()=>Date.now()),o="running"===s||"probing"===s||"between"===s;return((0,h.useEffect)(()=>{if(!o)return;let e=setInterval(()=>i(Date.now()),250);return()=>clearInterval(e)},[o]),"idle"===s)?null:"probing"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Checking APIs"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Probing each API before load. This can take a few seconds."})]}):"between"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Preparing next API"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Processing the last run and starting the next one. Sequence compares take a moment between APIs."}),r?(0,t.jsxs)("p",{className:"mt-1 font-mono text-sm text-ink",children:["Elapsed ",M(l-Date.parse(r))]}):null]}):"done"===s&&r&&n?(0,t.jsxs)("div",{className:"rounded-md border border-line bg-panel-2 px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-mute uppercase",children:"Overall time taken"}),(0,t.jsx)("p",{className:"mt-0.5 font-mono text-lg text-ink",children:(0,q.formatDuration)(r,n)}),(0,t.jsxs)("p",{className:"mt-0.5 text-xs text-mute",children:["Wall clock for the whole compare (",e,"), including probes and gaps between runs."]})]}):"running"!==s||0===a.length?null:(0,t.jsxs)("div",{className:"space-y-2",children:[a.map(e=>{let s=(0,O.expectedLoadMs)(e.report),a=Math.max(0,l-Date.parse(e.report.startedAt)),r=Math.max(0,s-a),n="running"===e.status&&0===r;return(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"text-xs tracking-wide text-accent uppercase",children:["queued"===e.status?"Starting":n?"Finishing":"Load running"," · ",e.title]}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:n?"Clock hit zero. k6 is letting in-flight requests finish.":`${L(a)} elapsed`})]}),(0,t.jsx)("div",{className:"font-mono text-2xl tabular text-ink",children:"queued"===e.status?"…":n?"—":L(r)})]},e.report.id)}),r?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Compare elapsed ",M(l-Date.parse(r))]}):null]})}var B=e.i(22543),J=e.i(63343),V=e.i(44794),H=e.i(31753),K=e.i(60566),_=e.i(39170),W=e.i(28867),X=e.i(56396);e.i(42674);var G=e.i(5305);let Z="apitestcenter-compare-draft";function Q(){return globalThis.crypto?.randomUUID?.()??`tab-${Date.now()}-${Math.random().toString(16).slice(2)}`}function Y(e){return{...(0,G.defaultRequestDraft)(),id:Q(),title:e}}function ee(){let e=Y("API 1");return{tabs:[e,Y("API 2")],activeId:e.id,load:{...G.DEFAULT_LOAD}}}function et(e,t){let s=e&&"object"==typeof e?e:{},a="string"==typeof s.title&&s.title.trim()||"string"==typeof s.label&&s.label.trim()||t;return{...(0,G.requestFromUnknown)(e),id:"string"==typeof s.id&&s.id?s.id:Q(),title:a}}var es=e.i(21206),ea=e.i(20054),er=e.i(68228),en=e.i(65638),el=e.i(6278),ei=e.i(46679),eo=e.i(727),ed=e.i(59180),ec=e.i(2603);let ep=new Set(["title"]);function em({tabs:e,activeId:s,probes:a,liveByTab:r,reports:l,running:i,onSelect:d,onRename:c,onClose:p,onAdd:u}){let[x,f]=(0,h.useState)(null);return(0,t.jsxs)("div",{className:"flex items-end gap-1 overflow-x-auto border-b border-line bg-canvas px-2 pt-2",role:"tablist","aria-label":"APIs to compare",children:[e.map((o,u)=>{let h=o.id===s,b=a[o.id],g=!!r[o.id],y=l.some(e=>e.tabId===o.id);return(0,t.jsxs)("div",{className:`group flex max-w-[15rem] shrink-0 items-center gap-1.5 rounded-t-md border border-b-0 pr-1 pl-2.5 text-sm ${h?"-mb-px border-line bg-panel text-ink":"border-transparent text-mute hover:bg-panel-2 hover:text-ink"}`,children:[(0,t.jsx)("span",{className:"h-2 w-2 shrink-0 rounded-full",style:{background:(0,z.seriesColor)(u)},"aria-hidden":!0}),x===o.id?(0,t.jsx)("input",{autoFocus:!0,defaultValue:o.title,"aria-label":"API name",onBlur:e=>{c(o.id,e.target.value.trim()||`API ${u+1}`),f(null)},onKeyDown:e=>{"Enter"===e.key&&e.target.blur(),"Escape"===e.key&&f(null)},className:"w-32 bg-transparent py-2 outline-none"}):(0,t.jsxs)("button",{type:"button",role:"tab","aria-selected":h,title:"Double-click to rename",onClick:()=>d(o.id),onDoubleClick:()=>f(o.id),className:"flex min-w-0 items-center gap-1.5 py-2",children:[(0,t.jsx)("span",{className:"truncate",children:o.title||"Untitled"}),g?(0,t.jsx)(n.Loader2,{size:12,className:"shrink-0 animate-spin text-accent","aria-label":"running"}):b?(0,t.jsx)("span",{className:`shrink-0 font-mono text-xs ${(0,es.isSuccess)(b)?"text-ok":"text-bad"}`,children:b.status||"ERR"}):y?(0,t.jsx)("span",{className:"shrink-0 text-xs text-ok",children:"done"}):null]}),e.length>2?(0,t.jsx)("button",{type:"button","aria-label":`Close ${o.title}`,disabled:i,onClick:()=>p(o.id),className:"rounded p-0.5 text-mute opacity-0 group-hover:opacity-100 hover:bg-panel-2 hover:text-bad focus:opacity-100 disabled:opacity-0",children:(0,t.jsx)(m.X,{size:12})}):null]},o.id)}),(0,t.jsxs)("button",{type:"button",onClick:u,disabled:e.length>=6||i,title:e.length>=6?"Up to 6 APIs":"Add an API",className:"mb-1 ml-1 inline-flex shrink-0 items-center gap-1 rounded-md px-2 py-1.5 text-xs text-mute hover:bg-panel-2 hover:text-ink disabled:opacity-40",children:[(0,t.jsx)(o.Plus,{size:14}),"Add API"]})]})}function eu({contract:e,blocked:s,skipped:a,busy:r,onProceed:n}){if(!e)return null;if("pass"===e.level)return(0,t.jsx)("p",{className:"rounded-md border border-ok/40 bg-ok/10 px-3 py-2 text-sm text-ok",children:"✓ Every API returned the same response structure."});let l=e.issues.filter(e=>!/Need at least two/.test(e.message));return(0,t.jsxs)("div",{role:s?"alert":void 0,className:"rounded-md border border-warn/40 bg-warn/10 px-3 py-2.5",children:[(0,t.jsx)("p",{className:"text-sm font-medium text-warn",children:s?"Compare not started — responses differ.":a?"Structures differ (allowed for this compare).":"Responses differ."}),l.length?(0,t.jsx)("ul",{className:"mt-1 list-disc space-y-0.5 pl-5 text-sm text-ink",children:l.map((e,s)=>(0,t.jsx)("li",{children:e.message},s))}):null,s?(0,t.jsx)("div",{className:"mt-2 flex flex-wrap gap-2",children:(0,t.jsx)("button",{type:"button",className:"btn btn-secondary py-1.5 text-xs",disabled:r,onClick:n,children:"Compare anyway"})}):null]})}function ex({entries:e,disabled:s,onPick:a}){let[n,l]=(0,h.useState)(!1),i=(0,h.useRef)(null);return(0,h.useEffect)(()=>{if(!n)return;let e=e=>!i.current?.contains(e.target)&&l(!1),t=e=>"Escape"===e.key&&l(!1);return document.addEventListener("pointerdown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("pointerdown",e),document.removeEventListener("keydown",t)}},[n]),(0,t.jsxs)("div",{ref:i,className:"relative",children:[(0,t.jsxs)("button",{type:"button",disabled:s,"aria-haspopup":"listbox","aria-expanded":n,onClick:()=>l(e=>!e),className:"inline-flex items-center gap-1 rounded-md border border-line px-2 py-1 text-xs text-mute hover:text-ink disabled:opacity-40",children:["Past compares",(0,t.jsx)(r.ChevronDown,{size:12})]}),n?(0,t.jsx)("ul",{role:"listbox","aria-label":"Past compares",className:"absolute right-0 z-30 mt-1 max-h-80 w-80 overflow-auto rounded-md border border-line bg-panel p-1 shadow-xl",children:e.map(e=>(0,t.jsx)("li",{role:"option","aria-selected":!1,children:(0,t.jsxs)("button",{type:"button",onClick:()=>{a(e),l(!1)},className:"flex w-full items-center justify-between gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",children:[(0,t.jsx)("span",{className:"min-w-0 truncate",children:e.name}),(0,t.jsxs)("span",{className:"shrink-0 text-mute",children:[e.titles.length," APIs"]})]})},e.id))}):null]})}function eh({children:e}){return(0,t.jsx)("div",{className:"flex flex-1 flex-col items-center justify-center rounded-lg border border-dashed border-line px-6 py-14 text-center text-sm text-mute",children:(0,t.jsx)("div",{className:"max-w-md",children:e})})}function ef(e,t){return function(e){let t=[];if(e.length<2)return{level:"fail",issues:[{level:"fail",message:"Need at least two APIs to compare"}]};for(let a of e){var s;a.probe.ok&&(s=a.probe.status)>=200&&s<300||t.push({level:"fail",message:`${a.label}: probe was ${a.probe.status||"ERR"}, not 2xx`}),a.probe.truncated&&t.push({level:"fail",message:`${a.label}: body was truncated, so the structure cannot be proven`})}let a=e.map(e=>({...e,structure:function(e){var t;let s,a=function(e,t){if(!e.trim())return"empty";if(t.toLowerCase().includes("json"))return"json";try{return JSON.parse(e),"json"}catch{return"text"}}(e.body,(s=Object.keys(t=e.headers).find(e=>"content-type"===e.toLowerCase()))?t[s]:"");if("empty"===a)return"empty";if("text"===a)return`text:${e.body}`;try{return`json:${JSON.stringify(function e(t){if(null===t)return"null";if(Array.isArray(t))return{type:"array",item:t.length>0?e(t[0]):"unknown"};if("object"==typeof t){let s={};for(let a of Object.keys(t).sort())s[a]=e(t[a]);return{type:"object",fields:s}}return typeof t}(JSON.parse(e.body)))}`}catch{return null}}(e.probe)}));if(a.some(e=>null==e.structure))t.push({level:"fail",message:"Could not parse one or more JSON bodies"});else{let e=a[0];if(e)for(let s of a.slice(1))s.structure!==e.structure&&t.push({level:"fail",message:`${s.label} response structure does not match ${e.label}`})}return{level:t.some(e=>"fail"===e.level)?"fail":t.some(e=>"warn"===e.level)?"warn":"pass",issues:t}}(e.map(e=>t[e.id]?{label:e.title||e.id,probe:t[e.id]}:null).filter(e=>!!e))}e.s(["ComparePage",0,function(){let e=(0,x.useSearchParams)(),s=(0,x.useRouter)(),r=(0,X.useToast)(),o=(0,_.useConfirm)(),f=(0,ea.useEngineHealth)(),b=(0,ec.useModKey)(),{slo:g}=(0,$.useSlo)(),{vars:y,activeEnv:v}=(0,el.useWorkspace)(),w=(0,h.useRef)(null),[j,k]=(0,h.useState)(ee),[N,I]=(0,h.useState)(!1),[S,C]=(0,h.useState)(!1),[P,F]=(0,h.useState)(null),[R,E]=(0,h.useState)({}),[T,z]=(0,h.useState)(null),[O,q]=(0,h.useState)(!1),[L,M]=(0,h.useState)("sequence"),[Q,eb]=(0,h.useState)(!1),[eg,ey]=(0,h.useState)(!1),[ev,ew]=(0,h.useState)(!1),[ej,ek]=(0,h.useState)(!1),[eN,eI]=(0,h.useState)({}),[eS,eC]=(0,h.useState)([]),[e$,eA]=(0,h.useState)(!1),[eP,eF]=(0,h.useState)(!1),{index:eR,refresh:eE}=(0,ed.useHistory)(),eT=eR?.compares??[],[ez,eD]=(0,h.useState)("idle"),[eO,eq]=(0,h.useState)(null),[eL,eM]=(0,h.useState)(null),[eU,eB]=(0,h.useState)("response"),eJ=(0,h.useRef)(!1),eV=(0,h.useRef)(new Set);(0,h.useEffect)(()=>{let t=function(){try{let e=sessionStorage.getItem(Z);if(!e)return null;let t=JSON.parse(e),s=[];if(Array.isArray(t.tabs)&&t.tabs.length>0)s=t.tabs.map((e,t)=>et(e,`API ${t+1}`)).slice(0,6);else{if(!t.a||!t.b)return null;s=[et(t.a,"API 1"),et(t.b,"API 2")]}let a="string"==typeof t.activeId&&s.some(e=>e.id===t.activeId)?t.activeId:s[0].id,r=(0,G.loadFromUnknown)(t.load??t);return{tabs:s,activeId:a,load:r}}catch{return null}}();t&&k(t);let s=e.get("compare"),a=(e.get("ids")??[e.get("a"),e.get("b")].filter(Boolean).join(",")).split(",").map(e=>e.trim()).filter(Boolean);s?ed.historyApi.compare(s).then(te).catch(()=>r("That compare is no longer in History","error")):a.length>=2&&Promise.all(a.map(e=>ed.historyApi.run(e).catch(()=>null))).then(e=>{let t=e.filter(e=>!!e);if(t.length<2)return r("Need at least two of those runs to overlay","error");eC(t.map((e,t)=>({tabId:e.report.id,title:e.meta?.name||e.report.testName||`API ${t+1}`,report:e.report}))),eA(!0),eF(!0),eD("done"),eB("results")}),I(!0)},[e]),(0,h.useEffect)(()=>{if(!N)return;let e=window.setTimeout(()=>(function(e){try{sessionStorage.setItem(Z,JSON.stringify(e))}catch{}})(j),250);return()=>window.clearTimeout(e)},[j,N]);let eH=j.tabs.find(e=>e.id===j.activeId)??j.tabs[0],eK=j.tabs.filter(G.isReady),e_=eK.length>=2,eW=(0,G.loadProblem)(j.load),eX=(0,h.useMemo)(()=>{let e=new Map(eS.map(e=>[e.tabId,e]));for(let[t,s]of Object.entries(eN)){if(e.has(t))continue;let a=j.tabs.find(e=>e.id===t);e.set(t,{tabId:t,title:a?.title??t,report:s.report})}let t=j.tabs.filter(t=>e.has(t.id)).map(t=>e.get(t.id));return t.length===e.size?t:[...e.values()]},[eS,eN,j.tabs]),eG=eS.map(e=>({id:e.tabId,title:e.title,report:e.report,probe:R[e.tabId]??null})),eZ=Object.entries(eN).map(([e,t])=>({title:j.tabs.find(t=>t.id===e)?.title||e,status:t.status,report:t.report}));function eQ(e,t){let s=j.tabs.find(t=>t.id===e);s&&Object.keys(t).some(e=>!ep.has(e)&&t[e]!==s[e])&&R[e]&&(E(({[e]:t,...s})=>s),z(null),q(!1)),k(s=>({...s,tabs:s.tabs.map(s=>s.id===e?t:s)}))}async function eY(e){try{let t=(0,G.resolveDraft)(e,y,v?.name),s=(0,G.buildPayload)(t,(0,G.toLoadConfig)(j.load),(0,G.autoRunName)(t,e.title),(0,G.targetsFromSlo)(g));return await (0,ei.withRunFirst)(s,t,y,v?.name)}catch(t){throw Error(`${e.title||"API"}: ${t instanceof Error?t.message:"invalid request"}`)}}async function e0(){let e;if(!S&&!ev&&(0,G.isReady)(eH)){try{e=await eY(eH)}catch(e){F(e instanceof Error?e.message:"Invalid request");return}C(!0),F(null),eB("response");try{let t=await (0,es.sendRequest)(e),s={...R,[eH.id]:t};E(s),z(ef(eK,s))}finally{C(!1)}}}async function e1(e,t){let s=Object.fromEntries(await Promise.all(e.map(async e=>[e.id,await (0,es.sendRequest)(t.get(e.id))])));return E(e=>({...e,...s})),s}async function e2(){let e;if(!S&&!ev&&e_){try{e=new Map(await Promise.all(eK.map(async e=>[e.id,await eY(e)])))}catch(e){F(e instanceof Error?e.message:"Invalid request");return}C(!0),F(null),q(!1);try{let t=await e1(eK,e),s=ef(eK,t);z(s),eB("response"),r("pass"===s.level?"Every API answered with the same structure":"Checked — see the structure result","pass"===s.level?"success":"info")}finally{C(!1)}}}async function e6(e,t){let s=0;for(;;){let a=await (0,es.fetchRun)(t);if(a){if(s=0,eI(t=>({...t,[e.id]:a})),(0,es.isTerminalStatus)(a.status))return eV.current.delete(t),eJ.current||eC(t=>[...t.filter(t=>t.tabId!==e.id),{tabId:e.id,title:e.title,report:a.report}]),eI(({[e.id]:t,...s})=>s),eJ.current?null:a.report}else if(++s>=20)throw Error(`Lost contact with the engine while ${e.title} was running`);await new Promise(e=>window.setTimeout(e,500))}}async function e5(e,t){let s=await (0,es.startLoadRun)(t);return eV.current.add(s.id),eI(t=>({...t,[e.id]:s})),s}async function e4(e,t){let s=[];for(let a=0;a<e.length&&!eJ.current;a++){let r=e[a];eD(a>0?"between":"running"),k(e=>({...e,activeId:r.id}));let n=await e5(r,t.get(r.id));eD("running");let l=await e6(r,n.id);if(!l)break;s.push({tabId:r.id,title:r.title,report:l})}return s}async function e3(e,t){eD("running");let s=await Promise.allSettled(e.map(e=>e5(e,t.get(e.id)))),a=s.find(e=>"rejected"===e.status);if(a)throw await e7(),a.reason instanceof Error?a.reason:Error("Failed to start load");return(await Promise.all(e.map(async(e,t)=>{let a=s[t].value,r=await e6(e,a.id);return r?{tabId:e.id,title:e.title,report:r}:null}))).filter(e=>!!e)}async function e8(e){let s;if(S||ev||!e_||!f.k6Ready)return;if(eW)return void F(eW);try{s=new Map(await Promise.all(eK.map(async e=>[e.id,await eY(e)])))}catch(e){F(e instanceof Error?e.message:"Invalid request");return}let a=eK.filter(e=>(0,es.needsLoadConfirm)(j.load.preset,s.get(e.id).load,s.get(e.id).request.url));if(a.length>0&&!await o({title:`Start a ${(0,J.profileSummary)(j.load)} load test against ${1===a.length?(0,es.hostOf)(s.get(a[0].id).request.url):`${a.length} hosts`}?`,body:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("ul",{className:"mb-2 list-disc pl-5 font-mono text-xs text-ink",children:a.map(e=>(0,t.jsx)("li",{children:(0,es.hostOf)(s.get(e.id).request.url)},e.id))}),"parallel"===L?"All APIs run at the same time":"APIs run one after another"," with"," ",(0,J.profileSummary)(j.load)," each. Only load-test systems you own or are allowed to test.",(0,t.jsxs)("span",{className:"mt-2 block",children:["Each simulated user sends its next request as soon as the last one returns, so a few dozen users can mean thousands of requests per second. Public sites and APIs behind a CDN or firewall usually answer that with ",(0,t.jsx)("span",{className:"text-ink",children:"429"})," or"," ",(0,t.jsx)("span",{className:"text-ink",children:"403"})," and may block this computer for a while — test a staging server, or use Requests per second mode with a modest rate."]})]}),confirmLabel:"Start compare",tone:"danger"}))return;let n=e||Q;eJ.current=!1,eV.current.clear(),F(null),C(!0),ew(!0),eA(!1),eF(!1),eC([]),eI({}),ey(!1),eq(new Date().toISOString()),eM(null),eD("probing"),eB("results");try{let e=await e1(eK,s),t=eK.filter(t=>!(0,es.isSuccess)(e[t.id]));if(t.length){F(`Every API needs a 2xx check before load. Not 2xx: ${t.map(t=>`${t.title} (${e[t.id]?.status||"error"})`).join(", ")}`),k(e=>({...e,activeId:t[0].id})),eB("response"),eD("idle");return}let a=ef(eK,e);if(z(a),"fail"===a.level&&!n){q(!0),eB("response"),eD("idle");return}q(!1),"fail"===a.level&&ey(!0);let l="parallel"===L?await e3(eK,s):await e4(eK,s);if(eM(new Date().toISOString()),l.length>=2&&!eJ.current){try{await ed.historyApi.saveCompare({mode:L,ignoreStructure:n,apis:l.map(t=>({id:t.tabId,title:t.title,report:t.report,probe:e[t.tabId]??null}))}),r("Compare finished and saved to History","success"),(0,eo.notifyFinished)({title:"Compare finished",body:`${l.map(e=>e.title).join(" vs ")}
|
|
51
|
-
Saved to History.`,ok:!0})}catch(e){r(`Compare finished, but saving it failed: ${e instanceof Error?e.message:"unknown error"}`,"error")}
|
|
50
|
+
</Relationships>`,"xl/styles.xml":k};for(let e of c)x[`xl/worksheets/sheet${e.id}.xml`]=e.xml;return new Blob([(0,w.zipStore)(x)],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})}async function S(e,t,s){let a=N().replace(/\.xlsx$/,""),r={[`${a}.xlsx`]:new Uint8Array(await (await I(e,t,s)).arrayBuffer()),[`${a}.json`]:(0,b.exportCompareJson)(e,t)};for(let t of e){if(!t.probe)continue;let e=t.title.replace(/[^\w.-]+/g,"-").slice(0,40)||t.id.slice(0,8);r[`${e}-probe.json`]=(0,b.exportProbeJson)(t.probe)}return{base:a,blob:(0,w.zipStore)(r)}}var C=e.i(15060),$=e.i(88153);function A({apis:e,mode:s,probes:a}){var n,l,i;let o,d,c,p,m,{slo:u}=(0,$.useSlo)(),x=N(),v=x.replace(/\.xlsx$/,""),j=Object.entries(a).filter(e=>!!e[1]),[k,F]=(0,h.useState)(!1),[R,E]=(0,h.useState)(null),[T,z]=(0,h.useState)(null);if(0===e.length)return null;let D=(n=e,l=s,i=u,o=n.map(e=>e.title),d=`Compare: ${o.join(" vs ")}`.slice(0,120),c=n.length>=2?(0,f.compareKpis)(n.map(e=>e.report)):[],p=[`APITestCenter compare (${l})`,"",...n.map(e=>`- ${e.title}: ${e.report.testName} [${e.report.status}]`),"",...c.map(e=>{let t=e.values.map((t,s)=>{var a,r;return`${o[s]}=${a=t,"ms"===(r=e.unit)?`${Math.round(a)}ms`:"rps"===r?`${a.toFixed(1)}/s`:"pct"===r?`${(100*a).toFixed(2)}%`:String(Math.round(a))}`}).join(", "),s=null==e.winner?"tie":o[e.winner]??"tie";return`${e.label}: ${t} (best: ${s})`})],i&&p.push("",`Performance targets: p95 ${i.p95Ms} ms, errors ${(100*i.errorRate).toFixed(1)}%`),p.push("","Attach the Excel or Zip export from APITestCenter."),{subject:d,body:m=p.join("\n"),mailto:`mailto:?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,gmail:`https://mail.google.com/mail/?view=cm&fs=1&tf=1&su=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,outlook:`https://outlook.office.com/mail/deeplink/compose?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`});async function O(){z(null),F(!1);try{let{base:t,blob:a}=await S(e,s,u),r={files:[new File([a],`${t}-export.zip`,{type:"application/zip"})],title:D.subject,text:D.body};if(navigator.canShare?.({files:r.files}))return void await navigator.share(r);E("mailto")}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;E("mailto"),z(e instanceof Error?e.message:"Share failed")}}return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("span",{className:"mr-1 flex items-center gap-1.5 text-xs text-mute",children:[(0,t.jsx)(g.Download,{size:14}),"Export"]}),(0,t.jsx)("button",{type:"button",disabled:e.length<2,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>void I(e,s,u).then(e=>(0,C.downloadBlob)(x,e)),children:"Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>(0,C.downloadText)(`${v}.json`,(0,b.exportCompareJson)(e,s),"application/json"),children:"JSON"}),(0,t.jsx)("button",{type:"button",disabled:0===j.length,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>{let t={};for(let[s,a]of j){let r=e.find(e=>e.id===s),n=(r?.title??s).replace(/[^\w.-]+/g,"-").slice(0,40);t[`${n}-probe.json`]=(0,b.exportProbeJson)(a)}(0,C.downloadBlob)(`${v}-probes.zip`,(0,w.zipStore)(t))},children:"Response JSONs"}),(0,t.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>void S(e,s,u).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:[(0,t.jsx)(g.Download,{size:12}),"Zip"]}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>F(e=>!e),className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",children:[(0,t.jsx)(y.Share2,{size:12}),"Share",(0,t.jsx)(r.ChevronDown,{size:12})]}),k?(0,t.jsxs)("div",{className:"absolute right-0 z-20 mt-1 w-56 rounded-md border border-line bg-panel p-1 shadow-lg",children:[(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("gmail")},children:"Gmail"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("outlook")},children:"Outlook on the web"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("mailto")},children:"Default mail app"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>void O(),children:"System share"})]}):null]})]}),T?(0,t.jsx)("p",{className:"max-w-md text-xs text-mute",children:T}):null,R?(0,t.jsx)(P,{apis:e,mode:s,target:R,links:D,onClose:()=>E(null)}):null]})}function P({apis:e,mode:s,target:a,links:r,onClose:n}){let{slo:l}=(0,$.useSlo)(),i={gmail:"Gmail",outlook:"Outlook on the web",mailto:"default mail app"},o="gmail"===a?r.gmail:"outlook"===a?r.outlook:r.mailto;return(0,t.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-canvas/70 p-4",role:"presentation",onClick:n,children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true",className:"w-full max-w-md rounded-lg border border-line bg-panel p-4 shadow-xl",onClick:e=>e.stopPropagation(),children:[(0,t.jsxs)("h2",{className:"text-sm font-medium text-ink",children:["Share via ",i[a]]}),(0,t.jsx)("p",{className:"mt-2 text-xs leading-5 text-mute",children:"Download the compare package, then attach it in the compose window. Browsers cannot attach files for you."}),(0,t.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void I(e,s,l).then(e=>(0,C.downloadBlob)(N(),e)),children:"Download Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void S(e,s,l).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:"Download Zip"}),(0,t.jsxs)("a",{href:o,target:"_blank",rel:"noreferrer",className:"rounded-md bg-accent px-2.5 py-1.5 text-xs font-medium text-canvas",onClick:n,children:["Open ",i[a]]}),(0,t.jsx)("button",{type:"button",className:"rounded-md px-2.5 py-1.5 text-xs text-mute",onClick:n,children:"Close"})]})]})})}var F=e.i(55658),R=e.i(53012),E=e.i(45404),T=e.i(29724),z=e.i(88231);function D({items:e,liveTabs:s,running:a,source:r,mode:l,slo:i,title:o,actions:d,status:c,exportBar:p}){let[m,u]=(0,h.useState)("all"),x=(0,h.useRef)(null),b=e.map((e,t)=>(0,f.compareSeriesLabel)(t,e.title)),g=a||!e.some(e=>e.tabId===m)?"all":m,y=e.filter(e=>!s.has(e.tabId)),v=!a&&y.length>=2?(0,F.compareFairness)(y.map(e=>e.report),y.map(t=>b[e.indexOf(t)])):null;return(0,t.jsxs)("div",{ref:x,className:"min-h-0 flex-1 overflow-y-auto",children:[(0,t.jsxs)("header",{className:"sticky top-0 z-10 border-b border-line bg-canvas/95 px-4 pt-3 backdrop-blur lg:px-6",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[(0,t.jsx)("h2",{className:"text-base font-medium text-ink",children:o}),(0,t.jsx)("div",{className:"ml-auto flex flex-wrap items-center gap-2",children:d})]}),(0,t.jsx)("div",{role:"tablist","aria-label":"Comparison or one run",className:"-mb-px mt-3 flex gap-1 overflow-x-auto",children:[{id:"all",label:"Comparison",color:null},...e.map((e,t)=>({id:e.tabId,label:b[t],color:(0,z.seriesColor)(t)}))].map(e=>{let r=g===e.id,l=s.has(e.id);return(0,t.jsxs)("button",{type:"button",role:"tab","aria-selected":r,disabled:a&&"all"!==e.id,title:a&&"all"!==e.id?"Each run's own report opens when the compare has finished":e.label,onClick:()=>{u(e.id),x.current?.scrollTo({top:0})},className:`flex max-w-[18rem] shrink-0 items-center gap-2 rounded-t-md border border-b-0 px-3 py-2 text-sm disabled:opacity-50 ${r?"border-line bg-panel font-medium text-ink":"border-transparent text-mute hover:bg-panel-2 hover:text-ink"}`,children:[e.color?(0,t.jsx)("span",{className:"h-2 w-2 shrink-0 rounded-full",style:{background:e.color},"aria-hidden":!0}):null,(0,t.jsx)("span",{className:"truncate",children:e.label}),l?(0,t.jsx)(n.Loader2,{size:12,className:"shrink-0 animate-spin text-accent","aria-label":"running"}):null]},e.id)})})]}),(0,t.jsx)("div",{className:"space-y-4 px-4 py-4 lg:px-6",children:"all"===g?(0,t.jsxs)(t.Fragment,{children:[c,p,v?.unfair?(0,t.jsxs)("p",{role:"note",className:"flex items-start gap-2 rounded-md border border-warn/40 bg-warn/10 px-3 py-2 text-sm text-ink",children:[(0,t.jsx)(R.AlertTriangle,{size:16,className:"mt-0.5 shrink-0 text-warn","aria-hidden":!0}),(0,t.jsxs)("span",{children:[v.unfair," Compare runs with the same load and length to say which API is faster."]})]}):null,(0,t.jsxs)("p",{className:"text-xs text-mute",children:["saved"===r?`Saved runs: ${e.map((e,t)=>{let s;return`${b[t]} ${Number.isNaN((s=new Date(e.report.startedAt)).getTime())?"":s.toLocaleString(void 0,{day:"numeric",month:"short",hour:"numeric",minute:"2-digit"})}`}).join(" · ")}.`:"parallel"===l?"Ran at the same time — the runs shared this computer's CPU and network, so treat the numbers as directional.":"Ran one after another with the same load.",v&&!v.unfair&&v.caveats.length?` Note: ${v.caveats.join("; ")}.`:""]}),e.length>=2?(0,t.jsx)(E.Dashboard,{scope:"compare",data:{reports:e.map(e=>e.report),titles:e.map((e,t)=>b[t]+(s.has(e.tabId)?" · live":"")),slo:i,live:a}}):(0,t.jsx)("p",{className:"rounded-lg border border-dashed border-line px-6 py-14 text-center text-sm text-mute",children:a?"The overlay appears when the first API is under way…":"The overlay needs at least two finished runs."})]}):(0,t.jsx)(T.ReportView,{report:e.find(e=>e.tabId===g).report,source:"engine"})})]})}var O=e.i(2385),q=e.i(19656);function L(e){let t=Math.max(0,Math.ceil(e/1e3)),s=Math.floor(t/60),a=t%60;return s>0?`${s}:${String(a).padStart(2,"0")}`:`${a}s`}function M(e){let t=Math.max(0,Math.round(e/1e3));if(t<60)return`${t}s`;let s=Math.floor(t/60),a=t%60;return a?`${s}m ${a}s`:`${s}m`}function U({mode:e,phase:s,liveRuns:a,startedAt:r,endedAt:n}){let[l,i]=(0,h.useState)(()=>Date.now()),o="running"===s||"probing"===s||"between"===s;return((0,h.useEffect)(()=>{if(!o)return;let e=setInterval(()=>i(Date.now()),250);return()=>clearInterval(e)},[o]),"idle"===s)?null:"probing"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Checking APIs"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Probing each API before load. This can take a few seconds."})]}):"between"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Preparing next API"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Processing the last run and starting the next one. Sequence compares take a moment between APIs."}),r?(0,t.jsxs)("p",{className:"mt-1 font-mono text-sm text-ink",children:["Elapsed ",M(l-Date.parse(r))]}):null]}):"done"===s&&r&&n?(0,t.jsxs)("div",{className:"rounded-md border border-line bg-panel-2 px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-mute uppercase",children:"Overall time taken"}),(0,t.jsx)("p",{className:"mt-0.5 font-mono text-lg text-ink",children:(0,q.formatDuration)(r,n)}),(0,t.jsxs)("p",{className:"mt-0.5 text-xs text-mute",children:["Wall clock for the whole compare (",e,"), including probes and gaps between runs."]})]}):"running"!==s||0===a.length?null:(0,t.jsxs)("div",{className:"space-y-2",children:[a.map(e=>{let s=(0,O.expectedLoadMs)(e.report),a=Math.max(0,l-Date.parse(e.report.startedAt)),r=Math.max(0,s-a),n="running"===e.status&&0===r;return(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"text-xs tracking-wide text-accent uppercase",children:["queued"===e.status?"Starting":n?"Finishing":"Load running"," · ",e.title]}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:n?"Clock hit zero. k6 is letting in-flight requests finish.":`${L(a)} elapsed`})]}),(0,t.jsx)("div",{className:"font-mono text-2xl tabular text-ink",children:"queued"===e.status?"…":n?"—":L(r)})]},e.report.id)}),r?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Compare elapsed ",M(l-Date.parse(r))]}):null]})}var B=e.i(22543),J=e.i(63343),V=e.i(44794),H=e.i(31753),K=e.i(60566),_=e.i(39170),W=e.i(28867),X=e.i(56396);e.i(42674);var G=e.i(5305);let Z="apitestcenter-compare-draft";function Q(){return globalThis.crypto?.randomUUID?.()??`tab-${Date.now()}-${Math.random().toString(16).slice(2)}`}function Y(e){return{...(0,G.defaultRequestDraft)(),id:Q(),title:e}}function ee(){let e=Y("API 1");return{tabs:[e,Y("API 2")],activeId:e.id,load:{...G.DEFAULT_LOAD}}}function et(e,t){let s=e&&"object"==typeof e?e:{},a="string"==typeof s.title&&s.title.trim()||"string"==typeof s.label&&s.label.trim()||t;return{...(0,G.requestFromUnknown)(e),id:"string"==typeof s.id&&s.id?s.id:Q(),title:a,collection:"string"==typeof s.collection&&s.collection?s.collection:void 0}}var es=e.i(21206),ea=e.i(20054),er=e.i(68228),en=e.i(65638),el=e.i(6278),ei=e.i(46679),eo=e.i(65238),ed=e.i(727),ec=e.i(59180),ep=e.i(2603);let em=new Set(["title"]);function eu({tabs:e,activeId:s,probes:a,liveByTab:r,reports:l,running:i,onSelect:d,onRename:c,onClose:p,onAdd:u}){let[x,f]=(0,h.useState)(null);return(0,t.jsxs)("div",{className:"flex items-end gap-1 overflow-x-auto border-b border-line bg-canvas px-2 pt-2",role:"tablist","aria-label":"APIs to compare",children:[e.map((o,u)=>{let h=o.id===s,b=a[o.id],g=!!r[o.id],y=l.some(e=>e.tabId===o.id);return(0,t.jsxs)("div",{className:`group flex max-w-[15rem] shrink-0 items-center gap-1.5 rounded-t-md border border-b-0 pr-1 pl-2.5 text-sm ${h?"-mb-px border-line bg-panel text-ink":"border-transparent text-mute hover:bg-panel-2 hover:text-ink"}`,children:[(0,t.jsx)("span",{className:"h-2 w-2 shrink-0 rounded-full",style:{background:(0,z.seriesColor)(u)},"aria-hidden":!0}),x===o.id?(0,t.jsx)("input",{autoFocus:!0,defaultValue:o.title,"aria-label":"API name",onBlur:e=>{c(o.id,e.target.value.trim()||`API ${u+1}`),f(null)},onKeyDown:e=>{"Enter"===e.key&&e.target.blur(),"Escape"===e.key&&f(null)},className:"w-32 bg-transparent py-2 outline-none"}):(0,t.jsxs)("button",{type:"button",role:"tab","aria-selected":h,title:"Double-click to rename",onClick:()=>d(o.id),onDoubleClick:()=>f(o.id),className:"flex min-w-0 items-center gap-1.5 py-2",children:[(0,t.jsx)("span",{className:"truncate",children:o.title||"Untitled"}),g?(0,t.jsx)(n.Loader2,{size:12,className:"shrink-0 animate-spin text-accent","aria-label":"running"}):b?(0,t.jsx)("span",{className:`shrink-0 font-mono text-xs ${(0,es.isSuccess)(b)?"text-ok":"text-bad"}`,children:b.status||"ERR"}):y?(0,t.jsx)("span",{className:"shrink-0 text-xs text-ok",children:"done"}):null]}),e.length>2?(0,t.jsx)("button",{type:"button","aria-label":`Close ${o.title}`,disabled:i,onClick:()=>p(o.id),className:"rounded p-0.5 text-mute opacity-0 group-hover:opacity-100 hover:bg-panel-2 hover:text-bad focus:opacity-100 disabled:opacity-0",children:(0,t.jsx)(m.X,{size:12})}):null]},o.id)}),(0,t.jsxs)("button",{type:"button",onClick:u,disabled:e.length>=6||i,title:e.length>=6?"Up to 6 APIs":"Add an API",className:"mb-1 ml-1 inline-flex shrink-0 items-center gap-1 rounded-md px-2 py-1.5 text-xs text-mute hover:bg-panel-2 hover:text-ink disabled:opacity-40",children:[(0,t.jsx)(o.Plus,{size:14}),"Add API"]})]})}function ex({contract:e,blocked:s,skipped:a,busy:r,onProceed:n}){if(!e)return null;if("pass"===e.level)return(0,t.jsx)("p",{className:"rounded-md border border-ok/40 bg-ok/10 px-3 py-2 text-sm text-ok",children:"✓ Every API returned the same response structure."});let l=e.issues.filter(e=>!/Need at least two/.test(e.message));return(0,t.jsxs)("div",{role:s?"alert":void 0,className:"rounded-md border border-warn/40 bg-warn/10 px-3 py-2.5",children:[(0,t.jsx)("p",{className:"text-sm font-medium text-warn",children:s?"Compare not started — responses differ.":a?"Structures differ (allowed for this compare).":"Responses differ."}),l.length?(0,t.jsx)("ul",{className:"mt-1 list-disc space-y-0.5 pl-5 text-sm text-ink",children:l.map((e,s)=>(0,t.jsx)("li",{children:e.message},s))}):null,s?(0,t.jsx)("div",{className:"mt-2 flex flex-wrap gap-2",children:(0,t.jsx)("button",{type:"button",className:"btn btn-secondary py-1.5 text-xs",disabled:r,onClick:n,children:"Compare anyway"})}):null]})}function eh({entries:e,disabled:s,onPick:a}){let[n,l]=(0,h.useState)(!1),i=(0,h.useRef)(null);return(0,h.useEffect)(()=>{if(!n)return;let e=e=>!i.current?.contains(e.target)&&l(!1),t=e=>"Escape"===e.key&&l(!1);return document.addEventListener("pointerdown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("pointerdown",e),document.removeEventListener("keydown",t)}},[n]),(0,t.jsxs)("div",{ref:i,className:"relative",children:[(0,t.jsxs)("button",{type:"button",disabled:s,"aria-haspopup":"listbox","aria-expanded":n,onClick:()=>l(e=>!e),className:"inline-flex items-center gap-1 rounded-md border border-line px-2 py-1 text-xs text-mute hover:text-ink disabled:opacity-40",children:["Past compares",(0,t.jsx)(r.ChevronDown,{size:12})]}),n?(0,t.jsx)("ul",{role:"listbox","aria-label":"Past compares",className:"absolute right-0 z-30 mt-1 max-h-80 w-80 overflow-auto rounded-md border border-line bg-panel p-1 shadow-xl",children:e.map(e=>(0,t.jsx)("li",{role:"option","aria-selected":!1,children:(0,t.jsxs)("button",{type:"button",onClick:()=>{a(e),l(!1)},className:"flex w-full items-center justify-between gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",children:[(0,t.jsx)("span",{className:"min-w-0 truncate",children:e.name}),(0,t.jsxs)("span",{className:"shrink-0 text-mute",children:[e.titles.length," APIs"]})]})},e.id))}):null]})}function ef({children:e}){return(0,t.jsx)("div",{className:"flex flex-1 flex-col items-center justify-center rounded-lg border border-dashed border-line px-6 py-14 text-center text-sm text-mute",children:(0,t.jsx)("div",{className:"max-w-md",children:e})})}function eb(e,t){return function(e){let t=[];if(e.length<2)return{level:"fail",issues:[{level:"fail",message:"Need at least two APIs to compare"}]};for(let a of e){var s;a.probe.ok&&(s=a.probe.status)>=200&&s<300||t.push({level:"fail",message:`${a.label}: probe was ${a.probe.status||"ERR"}, not 2xx`}),a.probe.truncated&&t.push({level:"fail",message:`${a.label}: body was truncated, so the structure cannot be proven`})}let a=e.map(e=>({...e,structure:function(e){var t;let s,a=function(e,t){if(!e.trim())return"empty";if(t.toLowerCase().includes("json"))return"json";try{return JSON.parse(e),"json"}catch{return"text"}}(e.body,(s=Object.keys(t=e.headers).find(e=>"content-type"===e.toLowerCase()))?t[s]:"");if("empty"===a)return"empty";if("text"===a)return`text:${e.body}`;try{return`json:${JSON.stringify(function e(t){if(null===t)return"null";if(Array.isArray(t))return{type:"array",item:t.length>0?e(t[0]):"unknown"};if("object"==typeof t){let s={};for(let a of Object.keys(t).sort())s[a]=e(t[a]);return{type:"object",fields:s}}return typeof t}(JSON.parse(e.body)))}`}catch{return null}}(e.probe)}));if(a.some(e=>null==e.structure))t.push({level:"fail",message:"Could not parse one or more JSON bodies"});else{let e=a[0];if(e)for(let s of a.slice(1))s.structure!==e.structure&&t.push({level:"fail",message:`${s.label} response structure does not match ${e.label}`})}return{level:t.some(e=>"fail"===e.level)?"fail":t.some(e=>"warn"===e.level)?"warn":"pass",issues:t}}(e.map(e=>t[e.id]?{label:e.title||e.id,probe:t[e.id]}:null).filter(e=>!!e))}e.s(["ComparePage",0,function(){let e=(0,x.useSearchParams)(),s=(0,x.useRouter)(),r=(0,X.useToast)(),o=(0,_.useConfirm)(),f=(0,ea.useEngineHealth)(),b=(0,ep.useModKey)(),{slo:g}=(0,$.useSlo)(),{vars:y,activeEnv:v}=(0,el.useWorkspace)(),w=(0,h.useRef)(null),[j,k]=(0,h.useState)(ee),[N,I]=(0,h.useState)(!1),[S,C]=(0,h.useState)(!1),[P,F]=(0,h.useState)(null),[R,E]=(0,h.useState)({}),[T,z]=(0,h.useState)(null),[O,q]=(0,h.useState)(!1),[L,M]=(0,h.useState)("sequence"),[Q,eg]=(0,h.useState)(!1),[ey,ev]=(0,h.useState)(!1),[ew,ej]=(0,h.useState)(!1),[ek,eN]=(0,h.useState)(!1),[eI,eS]=(0,h.useState)({}),[eC,e$]=(0,h.useState)([]),[eA,eP]=(0,h.useState)(!1),[eF,eR]=(0,h.useState)(!1),{index:eE,refresh:eT}=(0,ec.useHistory)(),ez=eE?.compares??[],[eD,eO]=(0,h.useState)("idle"),[eq,eL]=(0,h.useState)(null),[eM,eU]=(0,h.useState)(null),[eB,eJ]=(0,h.useState)("response"),eV=(0,h.useRef)(!1),eH=(0,h.useRef)(new Set);(0,h.useEffect)(()=>{let t=function(){try{let e=sessionStorage.getItem(Z);if(!e)return null;let t=JSON.parse(e),s=[];if(Array.isArray(t.tabs)&&t.tabs.length>0)s=t.tabs.map((e,t)=>et(e,`API ${t+1}`)).slice(0,6);else{if(!t.a||!t.b)return null;s=[et(t.a,"API 1"),et(t.b,"API 2")]}let a="string"==typeof t.activeId&&s.some(e=>e.id===t.activeId)?t.activeId:s[0].id,r=(0,G.loadFromUnknown)(t.load??t);return{tabs:s,activeId:a,load:r}}catch{return null}}();t&&k(t);let s=e.get("compare"),a=(e.get("ids")??[e.get("a"),e.get("b")].filter(Boolean).join(",")).split(",").map(e=>e.trim()).filter(Boolean);s?ec.historyApi.compare(s).then(tt).catch(()=>r("That compare is no longer in History","error")):a.length>=2&&Promise.all(a.map(e=>ec.historyApi.run(e).catch(()=>null))).then(e=>{let t=e.filter(e=>!!e);if(t.length<2)return r("Need at least two of those runs to overlay","error");e$(t.map((e,t)=>({tabId:e.report.id,title:e.meta?.name||e.report.testName||`API ${t+1}`,report:e.report}))),eP(!0),eR(!0),eO("done"),eJ("results")}),I(!0)},[e]),(0,h.useEffect)(()=>{if(!N)return;let e=window.setTimeout(()=>(function(e){try{sessionStorage.setItem(Z,JSON.stringify(e))}catch{}})(j),250);return()=>window.clearTimeout(e)},[j,N]);let eK=j.tabs.find(e=>e.id===j.activeId)??j.tabs[0],e_=j.tabs.filter(G.isReady),eW=e_.length>=2,eX=(0,G.loadProblem)(j.load),eG=(0,h.useMemo)(()=>{let e=new Map(eC.map(e=>[e.tabId,e]));for(let[t,s]of Object.entries(eI)){if(e.has(t))continue;let a=j.tabs.find(e=>e.id===t);e.set(t,{tabId:t,title:a?.title??t,report:s.report})}let t=j.tabs.filter(t=>e.has(t.id)).map(t=>e.get(t.id));return t.length===e.size?t:[...e.values()]},[eC,eI,j.tabs]),eZ=eC.map(e=>({id:e.tabId,title:e.title,report:e.report,probe:R[e.tabId]??null})),eQ=Object.entries(eI).map(([e,t])=>({title:j.tabs.find(t=>t.id===e)?.title||e,status:t.status,report:t.report}));function eY(e,t){let s=j.tabs.find(t=>t.id===e);s&&Object.keys(t).some(e=>!em.has(e)&&t[e]!==s[e])&&R[e]&&(E(({[e]:t,...s})=>s),z(null),q(!1)),k(s=>({...s,tabs:s.tabs.map(s=>s.id===e?t:s)}))}async function e0(e){try{let t=await (0,eo.withFolders)(e,e.collection,y),s=(0,G.resolveDraft)(t.draft,t.vars,v?.name),a=(0,G.buildPayload)(s,(0,G.toLoadConfig)(j.load),(0,G.autoRunName)(s,e.title),(0,G.targetsFromSlo)(g));return await (0,ei.withRunFirst)(a,s,y,v?.name)}catch(t){throw Error(`${e.title||"API"}: ${t instanceof Error?t.message:"invalid request"}`)}}async function e1(){let e;if(!S&&!ew&&(0,G.isReady)(eK)){try{e=await e0(eK)}catch(e){F(e instanceof Error?e.message:"Invalid request");return}C(!0),F(null),eJ("response");try{let t=await (0,es.sendRequest)(e),s={...R,[eK.id]:t};E(s),z(eb(e_,s))}finally{C(!1)}}}async function e2(e,t){let s=Object.fromEntries(await Promise.all(e.map(async e=>[e.id,await (0,es.sendRequest)(t.get(e.id))])));return E(e=>({...e,...s})),s}async function e6(){let e;if(!S&&!ew&&eW){try{e=new Map(await Promise.all(e_.map(async e=>[e.id,await e0(e)])))}catch(e){F(e instanceof Error?e.message:"Invalid request");return}C(!0),F(null),q(!1);try{let t=await e2(e_,e),s=eb(e_,t);z(s),eJ("response"),r("pass"===s.level?"Every API answered with the same structure":"Checked — see the structure result","pass"===s.level?"success":"info")}finally{C(!1)}}}async function e5(e,t){let s=0;for(;;){let a=await (0,es.fetchRun)(t);if(a){if(s=0,eS(t=>({...t,[e.id]:a})),(0,es.isTerminalStatus)(a.status))return eH.current.delete(t),eV.current||e$(t=>[...t.filter(t=>t.tabId!==e.id),{tabId:e.id,title:e.title,report:a.report}]),eS(({[e.id]:t,...s})=>s),eV.current?null:a.report}else if(++s>=20)throw Error(`Lost contact with the engine while ${e.title} was running`);await new Promise(e=>window.setTimeout(e,500))}}async function e4(e,t){let s=await (0,es.startLoadRun)(t);return eH.current.add(s.id),eS(t=>({...t,[e.id]:s})),s}async function e3(e,t){let s=[];for(let a=0;a<e.length&&!eV.current;a++){let r=e[a];eO(a>0?"between":"running"),k(e=>({...e,activeId:r.id}));let n=await e4(r,t.get(r.id));eO("running");let l=await e5(r,n.id);if(!l)break;s.push({tabId:r.id,title:r.title,report:l})}return s}async function e8(e,t){eO("running");let s=await Promise.allSettled(e.map(e=>e4(e,t.get(e.id)))),a=s.find(e=>"rejected"===e.status);if(a)throw await e9(),a.reason instanceof Error?a.reason:Error("Failed to start load");return(await Promise.all(e.map(async(e,t)=>{let a=s[t].value,r=await e5(e,a.id);return r?{tabId:e.id,title:e.title,report:r}:null}))).filter(e=>!!e)}async function e7(e){let s;if(S||ew||!eW||!f.k6Ready)return;if(eX)return void F(eX);try{s=new Map(await Promise.all(e_.map(async e=>[e.id,await e0(e)])))}catch(e){F(e instanceof Error?e.message:"Invalid request");return}let a=e_.filter(e=>(0,es.needsLoadConfirm)(j.load.preset,s.get(e.id).load,s.get(e.id).request.url));if(a.length>0&&!await o({title:`Start a ${(0,J.profileSummary)(j.load)} load test against ${1===a.length?(0,es.hostOf)(s.get(a[0].id).request.url):`${a.length} hosts`}?`,body:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("ul",{className:"mb-2 list-disc pl-5 font-mono text-xs text-ink",children:a.map(e=>(0,t.jsx)("li",{children:(0,es.hostOf)(s.get(e.id).request.url)},e.id))}),"parallel"===L?"All APIs run at the same time":"APIs run one after another"," with"," ",(0,J.profileSummary)(j.load)," each. Only load-test systems you own or are allowed to test.",(0,t.jsxs)("span",{className:"mt-2 block",children:["Each simulated user sends its next request as soon as the last one returns, so a few dozen users can mean thousands of requests per second. Public sites and APIs behind a CDN or firewall usually answer that with ",(0,t.jsx)("span",{className:"text-ink",children:"429"})," or"," ",(0,t.jsx)("span",{className:"text-ink",children:"403"})," and may block this computer for a while — test a staging server, or use Requests per second mode with a modest rate."]})]}),confirmLabel:"Start compare",tone:"danger"}))return;let n=e||Q;eV.current=!1,eH.current.clear(),F(null),C(!0),ej(!0),eP(!1),eR(!1),e$([]),eS({}),ev(!1),eL(new Date().toISOString()),eU(null),eO("probing"),eJ("results");try{let e=await e2(e_,s),t=e_.filter(t=>!(0,es.isSuccess)(e[t.id]));if(t.length){F(`Every API needs a 2xx check before load. Not 2xx: ${t.map(t=>`${t.title} (${e[t.id]?.status||"error"})`).join(", ")}`),k(e=>({...e,activeId:t[0].id})),eJ("response"),eO("idle");return}let a=eb(e_,e);if(z(a),"fail"===a.level&&!n){q(!0),eJ("response"),eO("idle");return}q(!1),"fail"===a.level&&ev(!0);let l="parallel"===L?await e8(e_,s):await e3(e_,s);if(eU(new Date().toISOString()),l.length>=2&&!eV.current){try{await ec.historyApi.saveCompare({mode:L,ignoreStructure:n,apis:l.map(t=>({id:t.tabId,title:t.title,report:t.report,probe:e[t.tabId]??null}))}),r("Compare finished and saved to History","success"),(0,ed.notifyFinished)({title:"Compare finished",body:`${l.map(e=>e.title).join(" vs ")}
|
|
51
|
+
Saved to History.`,ok:!0})}catch(e){r(`Compare finished, but saving it failed: ${e instanceof Error?e.message:"unknown error"}`,"error")}eT()}else eV.current&&r("Compare stopped","info");eO(eV.current?"idle":"done")}catch(e){F(e instanceof Error?e.message:"Compare failed"),eO("idle")}finally{eH.current.size>0&&await e9(),C(!1),ej(!1),eN(!1),eS({})}}async function e9(){await Promise.all([...eH.current].map(e=>(0,es.stopLoadRun)(e)))}async function te(){eV.current=!0,eN(!0),await e9()}function tt(e){e$(e.apis.map(e=>({tabId:e.id,title:e.title,report:e.report})));let t={};for(let s of e.apis)s.probe&&(t[s.id]=s.probe);E(t),M(e.mode),eg(!!e.meta?.ignoreStructure),ev(!!e.meta?.ignoreStructure),eP(!0),eR(!1),q(!1),z(null),eO("done");let s=e.apis.map(e=>Date.parse(e.report.startedAt)).filter(Number.isFinite),a=e.apis.map(e=>Date.parse(e.report.endedAt)).filter(Number.isFinite);eL(s.length?new Date(Math.min(...s)).toISOString():e.exportedAt),eU(a.length?new Date(Math.max(...a)).toISOString():e.exportedAt),eJ("results")}async function ts(e){try{tt(await ec.historyApi.compare(e.id))}catch(e){r(e instanceof Error?e.message:"Could not open that compare","error")}}(0,ep.useShortcuts)({send:()=>void e1(),run:()=>void e7(!1),focusUrl:()=>w.current?.focus()});let ta=R[eK.id],tr=f.k6Ready?eW?eX??void 0:"Give at least two APIs a URL":f.k6Label,tn=ez.length>0?(0,t.jsx)(eh,{entries:ez,disabled:ew,onPick:e=>void ts(e)}):null;if("results"===eB){let e=eG.length||e_.length;return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsx)("h1",{className:"sr-only",children:"Compare APIs"}),(0,t.jsx)(D,{items:eG,liveTabs:new Set(Object.keys(eI)),running:ew,source:eF?"saved":"compare",mode:L,slo:g,title:eF?`Comparing ${e} saved runs`:eA?`Saved compare \xb7 ${e} APIs`:ew?`Comparing ${e} APIs…`:`Compare results \xb7 ${e} APIs`,actions:ew?(0,t.jsxs)("button",{type:"button",className:"btn btn-danger",disabled:ek,onClick:()=>void te(),children:[ek?(0,t.jsx)(n.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(p.Square,{size:16}),ek?"Stopping…":"Stop"]}):(0,t.jsxs)(t.Fragment,{children:[tn,eA?(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary",onClick:()=>{e$([]),E({}),eP(!1),eR(!1),eO("idle"),eJ("response"),s.replace("/compare")},title:"Close these results and set up a new compare",children:[(0,t.jsx)(m.X,{size:16}),"Close"]}):(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary",onClick:()=>eJ("response"),title:"Back to the APIs and the shared load",children:[(0,t.jsx)(l,{size:16}),"Edit setup"]})]}),status:eF?null:(0,t.jsx)(U,{mode:L,phase:eD,liveRuns:eQ,startedAt:eq,endedAt:eM}),exportBar:eZ.length>0&&!ew?(0,t.jsx)(A,{apis:eZ,mode:L,probes:R}):null})]})}return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsx)("h1",{className:"sr-only",children:"Compare APIs"}),(0,t.jsx)(eu,{tabs:j.tabs,activeId:eK.id,probes:R,liveByTab:eI,reports:eC,running:ew,onSelect:e=>k(t=>({...t,activeId:e})),onRename:(e,t)=>eY(e,{...j.tabs.find(t=>t.id===e),title:t}),onClose:function(e){j.tabs.length<=2||ew||(k(t=>{let s=t.tabs.findIndex(t=>t.id===e),a=t.tabs.filter(t=>t.id!==e),r=t.activeId===e?a[Math.max(0,s-1)]?.id??a[0].id:t.activeId;return{...t,tabs:a,activeId:r}}),E(({[e]:t,...s})=>s),e$(t=>t.filter(t=>t.tabId!==e)))},onAdd:function(){if(j.tabs.length>=6)return;let e=Y(`API ${j.tabs.length+1}`);k(t=>({...t,tabs:[...t.tabs,e],activeId:e.id})),window.setTimeout(()=>w.current?.focus(),0)}}),(0,t.jsxs)("header",{className:"border-b border-line bg-panel px-4 py-3 lg:px-6",children:[(0,t.jsx)(V.RequestBar,{ref:w,draft:eK,onChange:e=>eY(eK.id,{...eK,...e}),onImported:e=>r(e,"success"),actions:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",disabled:S||ew||!(0,G.isReady)(eK),title:`Send this API once (${b}+Enter)`,onClick:()=>void e1(),children:[S&&!ew?(0,t.jsx)(n.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(d.Send,{size:16}),"Send"]}),(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary",disabled:S||ew||!eW,title:"Send every API once and compare response structure",onClick:()=>void e6(),children:[(0,t.jsx)(c,{size:16}),"Send all"]}),ew?(0,t.jsxs)("button",{type:"button",className:"btn btn-danger",disabled:ek,onClick:()=>void te(),children:[ek?(0,t.jsx)(n.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(p.Square,{size:16}),ek?"Stopping…":"Stop"]}):(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary",disabled:S||!!tr,title:tr??`Check every API, then run the shared load on each (${b}+Shift+Enter)`,onClick:()=>void e7(!1),children:[(0,t.jsx)(i.Play,{size:16}),"Compare load"]})]})}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-x-4 gap-y-2",children:[(0,t.jsx)(er.EnvironmentBar,{drafts:j.tabs,collections:j.tabs.map(e=>e.collection)}),(0,t.jsx)(en.RequestPicker,{onOpen:e=>{eY(eK.id,{...eK,...(0,G.requestFromUnknown)(e.request),id:eK.id,title:e.name,collection:e.collection||void 0}),r(`Loaded “${e.name}” into this tab`,"success")}}),P?(0,t.jsx)("p",{role:"alert",className:"text-xs text-bad",children:P}):null]})]}),(0,t.jsxs)("div",{className:"grid min-h-0 flex-1 overflow-y-auto lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)] lg:overflow-hidden 2xl:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]",children:[(0,t.jsxs)("section",{"aria-label":"Request",className:"min-w-0 space-y-6 px-4 py-4 lg:overflow-y-auto lg:px-6",children:[(0,t.jsx)(H.RequestEditor,{id:"compare-request",draft:eK,collection:eK.collection,onChange:e=>eY(eK.id,{...eK,...e}),checkResults:R[eK.id]?.checks,setupResult:R[eK.id]?.setup}),(0,t.jsxs)("section",{className:"space-y-4 rounded-lg border border-line bg-panel p-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("h2",{className:"flex items-center gap-1.5 text-sm font-medium text-ink",children:["Compare setup",(0,t.jsx)(B.Hint,{text:"These settings apply to every API, so their timelines line up in the overlay."})]}),(0,t.jsxs)("p",{className:"mt-0.5 text-xs text-mute",children:["Applies to all ",j.tabs.length," APIs."]})]}),(0,t.jsx)(J.LoadEditor,{load:j.load,onChange:e=>k(t=>({...t,load:e}))}),(0,t.jsxs)("div",{className:"space-y-2 border-t border-line pt-4",children:[(0,t.jsx)("span",{className:"block text-xs text-mute",children:"Run mode"}),(0,t.jsx)(W.Segmented,{label:"Run mode",value:L,onChange:M,options:[{value:"sequence",label:"One after another"},{value:"parallel",label:"All at once"}]}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"sequence"===L?"Fairest comparison: each API gets this computer's full CPU and network.":"Faster, but the runs share CPU and network, so treat the numbers as directional."}),(0,t.jsxs)("label",{className:"flex items-start gap-2 pt-1 text-sm text-ink",children:[(0,t.jsx)("input",{type:"checkbox",checked:Q,onChange:e=>eg(e.target.checked),className:"mt-1 accent-[var(--accent)]"}),(0,t.jsxs)("span",{children:["Allow different response structures",(0,t.jsx)("span",{className:"block text-xs text-mute",children:"By default every API must return the same JSON shape, so you compare like with like. Each still needs a 2xx."})]})]})]})]})]}),(0,t.jsxs)("section",{"aria-label":"Response",className:"@container flex min-h-[32rem] min-w-0 flex-col border-line bg-panel/40 px-4 py-4 lg:min-h-0 lg:overflow-y-auto lg:border-l lg:px-6",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-line pb-2",children:[(0,t.jsxs)("h2",{className:"text-sm font-medium text-ink",children:["Response · ",eK.title||"API",ta?(0,t.jsx)("span",{className:`ml-2 font-mono text-xs ${(0,es.isSuccess)(ta)?"text-ok":"text-bad"}`,children:ta.status||"ERR"}):null]}),(0,t.jsxs)("div",{className:"ml-auto flex items-center gap-2",children:[tn,eG.length>=2?(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1 text-xs",onClick:()=>eJ("results"),children:["View results",(0,t.jsx)(a,{size:14})]}):null]})]}),(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col space-y-4 pt-4",children:[(0,t.jsx)(ex,{contract:T,blocked:O,skipped:ey,busy:S||ew,onProceed:()=>void e7(!0)}),ta?(0,t.jsx)(K.ResponseViewer,{result:ta}):(0,t.jsxs)(ef,{children:[(0,t.jsxs)("p",{children:["Give each tab a URL, choose the shared load, then press ",(0,t.jsx)("span",{className:"text-ink",children:"Compare load"}),". Each API is checked first; the results open full width, with a tab for each API."]}),(0,t.jsxs)("p",{className:"mt-2",children:[(0,t.jsx)("span",{className:"text-ink",children:"Send"})," checks this API once; ",(0,t.jsx)("span",{className:"text-ink",children:"Send all"})," checks every API and confirms they return the same structure. To compare finished runs, use ",(0,t.jsx)("span",{className:"text-ink",children:"Add to compare"})," on a report, or tick runs on"," ",(0,t.jsx)(u.default,{href:"/history",className:"text-accent hover:underline",children:"History"}),"."]})]})]})]})]})]})}],49186)}]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,33622,e=>{"use strict";var t=e.i(61666);e.i(24856);var r=e.i(48191);function n(e){return!!e&&"object"==typeof e&&"string"==typeof e.id&&"string"==typeof e.testName&&Array.isArray(e.buckets)&&"object"==typeof e.summary&&null!==e.summary}var a=e.i(45404),s=e.i(29724),o=e.i(88153),l=e.i(56396),i=e.i(59180),c=e.i(67938),p=e.i(50804),d=e.i(83067);e.s(["default",0,function(){let[e,u]=(0,d.useState)(null),[x,f]=(0,d.useState)(null),[m,h]=(0,d.useState)(null),[y,b]=(0,d.useState)(null),[j,g]=(0,d.useState)(!1),[v,N]=(0,d.useState)(!1),[w,S]=(0,d.useState)(null),[O,k]=(0,d.useState)(!1),A=(0,l.useToast)(),{refresh:
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,33622,e=>{"use strict";var t=e.i(61666);e.i(24856);var r=e.i(48191);function n(e){return!!e&&"object"==typeof e&&"string"==typeof e.id&&"string"==typeof e.testName&&Array.isArray(e.buckets)&&"object"==typeof e.summary&&null!==e.summary}var a=e.i(45404),s=e.i(29724),o=e.i(88153),l=e.i(56396),i=e.i(59180),c=e.i(67938),p=e.i(50804),d=e.i(83067);e.s(["default",0,function(){let[e,u]=(0,d.useState)(null),[x,f]=(0,d.useState)(null),[m,h]=(0,d.useState)(null),[y,b]=(0,d.useState)(null),[j,g]=(0,d.useState)(!1),[v,N]=(0,d.useState)(!1),[w,S]=(0,d.useState)(null),[O,k]=(0,d.useState)(!1),A=(0,l.useToast)(),{refresh:T}=(0,i.useHistory)();async function C(){k(!0);try{await i.historyApi.import(w),await T(),N(!0),A("Saved to History","success")}catch(e){A(e instanceof Error?e.message:"Could not save to History","error")}finally{k(!1)}}let U=(0,d.useCallback)(async e=>{h(null),N(!1),u(null),f(null);let t=e.name.toLowerCase();if(t.endsWith(".html")||t.endsWith(".xlsx")||t.endsWith(".csv")||t.endsWith(".zip")){b(e.name),h("Preview needs the JSON export from the lab. HTML and Excel are for sharing, not for opening back here.");return}try{let t=await e.text(),a=JSON.parse(t),s=function(e){if(!e||"object"!=typeof e)throw Error("That file is not JSON we can open.");if("compare"===e.kind||Array.isArray(e.apis)&&e.apis.length>0){if(!(e&&"object"==typeof e&&"compare"===e.kind&&Array.isArray(e.apis)&&e.apis.length>=1&&e.apis.every(e=>e&&"object"==typeof e&&n(e.report))))throw Error("Not a valid APITestCenter compare export.");return{kind:"compare",doc:{...e,apis:e.apis.map(e=>({...e,report:(0,r.repairSummary)(e.report)}))}}}if(n(e.report))return{kind:"report",report:(0,r.repairSummary)(e.report)};if(n(e))return{kind:"report",report:(0,r.repairSummary)(e)};throw Error("Not an APITestCenter report. Export JSON from the lab (not HTML or Excel).")}(a);S(a),b(e.name),"compare"===s.kind?f(s.doc):u(s.report)}catch(t){b(e.name),h(t instanceof Error?t.message:"Could not read that file.")}},[]);function E(e){e.preventDefault(),g(!0)}function D(e){e.preventDefault(),g(!1);let t=e.dataTransfer.files[0];t&&U(t)}let H=j?"border-accent bg-accent-dim":"border-line bg-panel",L=x?.apis.map(e=>e.title)??[],{slo:R}=(0,o.useSlo)();return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col p-6 lg:p-8",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h1",{className:"text-xl font-medium text-ink",children:"Open a report"}),(0,t.jsx)("p",{className:"mt-1 max-w-xl text-sm text-mute",children:"Reopen a JSON report you exported earlier — a single run or a compare. Excel and HTML exports are for sharing and can't be reopened."})]}),e||x?(0,t.jsxs)("label",{onDragOver:E,onDragLeave:()=>g(!1),onDrop:D,className:`inline-flex cursor-pointer items-center gap-2 rounded-md border border-dashed px-3 py-2 text-xs ${H}`,children:[(0,t.jsx)(c.FileUp,{size:14,className:"text-accent"}),"Replace JSON",(0,t.jsx)("input",{type:"file",accept:"application/json,.json",className:"sr-only",onChange:e=>{let t=e.target.files?.[0];t&&U(t),e.target.value=""}})]}):null]}),m?(0,t.jsx)("p",{className:"mt-4 text-sm text-bad",children:m}):null,x?(0,t.jsxs)("div",{className:"mt-6 space-y-4",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,t.jsxs)("p",{className:"text-xs text-mute",children:[y," · compare · ",x.mode]}),(0,t.jsx)("button",{type:"button",disabled:v||O,onClick:()=>void C(),className:"rounded-md border border-line px-3 py-1.5 text-xs text-ink hover:border-accent disabled:opacity-40",children:v?"Saved to History":"Keep in History"})]}),(0,t.jsx)(a.Dashboard,{scope:"compare",data:{reports:x.apis.map(e=>e.report),titles:L,slo:R,live:!1}}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Open"," ",(0,t.jsx)(p.default,{href:"/compare",className:"text-accent hover:underline",children:"Compare"})," ","to re-run these APIs live."]})]}):e?(0,t.jsxs)("div",{className:"mt-6 space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,t.jsx)("p",{className:"text-xs text-mute",children:y}),(0,t.jsx)("button",{type:"button",disabled:v||O,onClick:()=>void C(),className:"rounded-md border border-line px-3 py-1.5 text-xs text-ink hover:border-accent disabled:opacity-40",children:v?"Saved to History":"Keep in History"})]}),v?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Open it anytime on"," ",(0,t.jsx)(p.default,{href:"/history",className:"text-accent hover:underline",children:"History"}),"."]}):null,(0,t.jsx)("div",{className:"rounded-lg border border-line bg-panel p-4",children:(0,t.jsx)(s.ReportView,{report:e,source:"file"})})]}):(0,t.jsxs)("label",{onDragOver:E,onDragLeave:()=>g(!1),onDrop:D,className:`mt-6 flex min-h-0 flex-1 cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed px-8 py-16 text-center ${H}`,children:[(0,t.jsx)(c.FileUp,{size:28,className:"text-accent"}),(0,t.jsx)("span",{className:"mt-4 text-base text-ink",children:"Drop a JSON report here, or click to choose"}),(0,t.jsx)("span",{className:"mt-2 max-w-md text-sm text-mute",children:"Single-run or compare JSON from Export. HTML, Excel, and zip are for sharing — they will not open here."}),(0,t.jsx)("span",{className:"mt-4 font-mono text-xs text-mute",children:"apitestcenter-*.json"}),(0,t.jsx)("input",{type:"file",accept:"application/json,.json",className:"sr-only",onChange:e=>{let t=e.target.files?.[0];t&&U(t),e.target.value=""}})]})]})}],33622)},17219,15060,e=>{"use strict";let t=new Uint32Array(256).map((e,t)=>{let r=t;for(let e=0;e<8;e++)r=1&r?0xedb88320^r>>>1:r>>>1;return r>>>0});function r(e){let t=new Uint8Array(2);return new DataView(t.buffer).setUint16(0,e,!0),t}function n(e){let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),t}function a(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),r=0;for(let n of e)t.set(n,r),r+=n.length;return t}function s(e,t){let r=URL.createObjectURL(t),n=document.createElement("a");n.href=r,n.download=e,document.body.appendChild(n),n.click(),n.remove(),URL.revokeObjectURL(r)}e.s(["zipStore",0,function(e){let s=new TextEncoder,o=[],l=[],i=0;for(let[c,p]of Object.entries(e)){let e=s.encode(c),d="string"==typeof p?s.encode(p):p,u=function(e){let r=0xffffffff;for(let n of e)r=t[(r^n)&255]^r>>>8;return(0xffffffff^r)>>>0}(d),x=a([n(0x4034b50),r(20),r(0),r(0),r(0),r(0),n(u),n(d.length),n(d.length),r(e.length),r(0),e,d]),f=a([n(0x2014b50),r(20),r(20),r(0),r(0),r(0),r(0),n(u),n(d.length),n(d.length),r(e.length),r(0),r(0),r(0),r(0),n(0),n(i),e]);o.push(x),l.push(f),i+=x.length}let c=a(l),p=a([n(0x6054b50),r(0),r(0),r(Object.keys(e).length),r(Object.keys(e).length),n(c.length),n(i),r(0)]),d=a([...o,c,p]);return new Blob([d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)],{type:"application/zip"})}],17219),e.s(["downloadBlob",0,s,"downloadText",0,function(e,t,r){s(e,new Blob([t],{type:r}))}],15060)}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,63343,44794,60566,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(59100),a=e.i(71189),n=e.i(87283),r=e.i(83067),l=e.i(22543),i=e.i(31753),o=e.i(28867);e.i(42674);var d=e.i(5305);let c={smoke:"2 users for 30s. Proves the endpoint works under a little concurrency.",average:"10 users for 5m. Typical day-to-day traffic.",stress:"Ramp to 20 users, hold 1m, ramp down. Looks for the breaking point.",spike:"5 users, a sudden jump to 50, then back to 5. Does it survive the burst and recover?",soak:"10 users for 30m. Finds memory leaks and slow degradation that short tests miss.",custom:"Your own numbers."};function u({label:e,value:s,min:a,max:n,onChange:r,hint:i}){return(0,t.jsxs)("label",{className:"block",children:[(0,t.jsxs)("span",{className:"mb-1 flex items-center gap-1 text-xs text-mute",children:[e,i?(0,t.jsx)(l.Hint,{label:`About ${e}`,text:i}):null]}),(0,t.jsx)("input",{type:"number",min:a,max:n,value:s,onChange:e=>r(h(e.target.value,a,n)),className:"input font-mono"})]})}function m({stages:e,unit:s,rate:r,onChange:l}){let i=(t,s)=>l(e.map((e,a)=>a===t?{...e,...s}:e));return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)("p",{className:"text-xs text-mute",children:"Each stage moves linearly to its target over its duration. Hold steady by repeating the same target."}),(0,t.jsxs)("div",{className:"overflow-hidden rounded-md border border-line",children:[(0,t.jsxs)("div",{className:"grid grid-cols-[2.5rem_minmax(0,1fr)_minmax(0,1fr)_2rem] bg-panel-2 text-xs text-mute",children:[(0,t.jsx)("span",{className:"px-2 py-1.5",children:"#"}),(0,t.jsx)("span",{className:"border-l border-line px-2 py-1.5",children:"Duration"}),(0,t.jsxs)("span",{className:"border-l border-line px-2 py-1.5",children:["Target (",s,")"]}),(0,t.jsx)("span",{})]}),e.map((s,a)=>{let o=(0,d.durationError)(s.duration,!1);return(0,t.jsxs)("div",{className:"grid grid-cols-[2.5rem_minmax(0,1fr)_minmax(0,1fr)_2rem] border-t border-line",children:[(0,t.jsx)("span",{className:"px-2 py-1.5 font-mono text-xs text-mute",children:a+1}),(0,t.jsx)("input",{"aria-label":`Stage ${a+1} duration`,"aria-invalid":!!o||void 0,title:o,value:s.duration,onChange:e=>i(a,{duration:e.target.value}),className:`min-w-0 border-l border-line bg-transparent px-2 py-1.5 font-mono text-[13px] outline-none focus:bg-panel-2 ${o?"text-bad":"text-ink"}`}),(0,t.jsx)("input",{"aria-label":`Stage ${a+1} target`,type:"number",min:0,max:r?1e5:500,value:s.target,onChange:e=>i(a,{target:h(e.target.value,0,r?1e5:500)}),className:"min-w-0 border-l border-line bg-transparent px-2 py-1.5 font-mono text-[13px] text-ink outline-none focus:bg-panel-2"}),(0,t.jsx)("button",{type:"button","aria-label":`Remove stage ${a+1}`,disabled:e.length<=1,onClick:()=>l(e.filter((e,t)=>t!==a)),className:"grid place-items-center text-mute hover:text-bad disabled:opacity-30",children:(0,t.jsx)(n.X,{size:13})})]},a)})]}),(0,t.jsxs)("button",{type:"button",disabled:e.length>=20,onClick:()=>l([...e,{duration:"30s",target:e[e.length-1]?.target??1}]),className:"inline-flex items-center gap-1 text-xs text-accent hover:underline disabled:opacity-40",children:[(0,t.jsx)(a.Plus,{size:12,"aria-hidden":!0})," Add stage"]})]})}function h(e,t,s){let a=Math.round(Number(e));return Number.isFinite(a)?Math.min(s,Math.max(t,a)):t}function x(e){let t="rate"===e.mode;if(e.stages&&e.stages.length){let t=[[0,0]],a=0;for(let n of e.stages)a+=(0,s.durationToMs)(n.duration),t.push([a,n.target]);return{points:t,totalMs:a,peak:Math.max(0,...e.stages.map(e=>e.target))}}let a=t?e.rps??20:e.vus,n=(0,s.durationToMs)(e.rampUp),r=(0,s.durationToMs)(e.duration),l=(0,s.durationToMs)(e.rampDown);return{points:[[0,n>0?0:a],[n,a],[n+r,a],[n+r+l,l>0?0:a]],totalMs:n+r+l,peak:a}}function p(e){let{totalMs:t,peak:s}=x(e),a="rate"===e.mode?"req/s":1===s?"VU":"VUs";return`${e.stages?.length?"peak ":""}${s.toLocaleString()} ${a} \xb7 ${f(t)}`}function f(e){let t=Math.round(e/1e3);if(t<60)return`${t}s`;let s=Math.floor(t/60);return s<60?t%60?`${s}m ${t%60}s`:`${s}m`:`${Math.floor(s/60)}h ${s%60}m`}function b({load:e}){let{points:s,totalMs:a,peak:n}=x(e),r=s.map(([e,t])=>`${e/Math.max(a,1)*300},${56-t/Math.max(n,1)*50}`).join(" "),l=`0,56 ${r} 300,56`;return(0,t.jsxs)("figure",{className:"rounded-md border border-line bg-panel-2 px-3 py-2",children:[(0,t.jsxs)("figcaption",{className:"mb-1 flex justify-between text-xs text-mute",children:[(0,t.jsx)("span",{children:"Planned load"}),(0,t.jsx)("span",{className:"font-mono text-ink",children:p(e)})]}),(0,t.jsxs)("svg",{viewBox:"0 0 300 56",preserveAspectRatio:"none",className:"h-14 w-full",role:"img","aria-label":`Load profile: ${p(e)}`,children:[(0,t.jsx)("polygon",{points:l,fill:"var(--series-1)",fillOpacity:.15}),(0,t.jsx)("polyline",{points:r,fill:"none",stroke:"var(--series-1)",strokeWidth:2,vectorEffect:"non-scaling-stroke"})]}),(0,t.jsxs)("div",{className:"mt-1 flex justify-between font-mono text-[11px] text-mute",children:[(0,t.jsx)("span",{children:"0s"}),(0,t.jsx)("span",{children:"rate"===e.mode?"requests per second":"simulated users"}),(0,t.jsx)("span",{children:f(a)})]})]})}e.s(["LoadEditor",0,function({load:e,onChange:a}){let[n,h]=(0,r.useState)(!1),x=t=>a({...e,...t,preset:"custom"}),p="rate"===e.mode,f=!!(e.stages&&e.stages.length);return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(o.Segmented,{label:"Load preset",value:e.preset,onChange:t=>a((0,d.applyPreset)(e,t)),options:[{value:"smoke",label:"Smoke"},{value:"average",label:"Average"},{value:"stress",label:"Stress"},{value:"spike",label:"Spike"},{value:"soak",label:"Soak"},{value:"custom",label:"Custom"}]}),(0,t.jsx)("p",{className:"mt-2 text-xs text-mute",children:c[e.preset]})]}),(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("span",{className:"mb-1 flex items-center gap-1 text-xs text-mute",children:["Drive load by",(0,t.jsx)(l.Hint,{label:"About users vs rate",text:"Simulated users (VUs): N clients each send, wait for the answer, and send again — a slow API gets fewer requests. Requests per second: k6 holds the rate whatever the API does — the honest way to test capacity."})]}),(0,t.jsx)(o.Segmented,{label:"Drive load by",value:e.mode??"users",onChange:e=>x({mode:e}),options:[{value:"users",label:"Simulated users"},{value:"rate",label:"Requests per second"}]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Shape"}),(0,t.jsx)(o.Segmented,{label:"Load shape",value:f?"stages":"simple",onChange:function(t){if("simple"===t)return x({stages:null});let a=p?e.rps??20:e.vus,n=[];(0,s.durationToMs)(e.rampUp)>0&&n.push({duration:e.rampUp,target:a}),n.push({duration:e.duration,target:a}),(0,s.durationToMs)(e.rampDown)>0&&n.push({duration:e.rampDown,target:0}),x({stages:n})},options:[{value:"simple",label:"Ramp · hold · down"},{value:"stages",label:"Step by step"}]})]})]}),f?(0,t.jsx)(m,{stages:e.stages,unit:p?"req/s":"VUs",rate:p,onChange:e=>x({stages:e})}):(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[p?(0,t.jsx)(u,{label:"Requests / second",value:e.rps??20,min:1,max:1e5,onChange:e=>x({rps:e})}):(0,t.jsx)(u,{label:"Simulated users",hint:"Concurrent clients running from this computer. 50+ will load both the API and this machine.",value:e.vus,min:1,max:500,onChange:e=>x({vus:e})}),(0,t.jsx)(i.LabeledInput,{label:"Hold for",mono:!0,value:e.duration,error:(0,d.durationError)(e.duration,!1),onChange:e=>x({duration:e})}),(0,t.jsx)(i.LabeledInput,{label:"Ramp up",mono:!0,value:e.rampUp,error:(0,d.durationError)(e.rampUp),onChange:e=>x({rampUp:e})}),(0,t.jsx)(i.LabeledInput,{label:"Ramp down",mono:!0,value:e.rampDown,error:(0,d.durationError)(e.rampDown),onChange:e=>x({rampDown:e})})]}),p?(0,t.jsx)("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:(0,t.jsx)(u,{label:"Max simulated users",hint:"k6 starts more VUs when responses slow down, up to this ceiling. If it runs out, requests are dropped and the report says how many.",value:e.maxVus??100,min:1,max:2e3,onChange:e=>x({maxVus:e})})}):null,(0,t.jsx)(b,{load:e}),(0,t.jsx)("button",{type:"button",className:"text-xs text-accent hover:underline",onClick:()=>h(e=>!e),"aria-expanded":n,children:n?"Hide pacing options":"Pacing options"}),n?(0,t.jsxs)("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-3",children:[p?(0,t.jsx)("p",{className:"text-xs text-mute sm:col-span-2",children:"Think time does not apply when holding a request rate — k6 paces the requests itself."}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(u,{label:"Think time (ms)",value:e.thinkTimeMs,min:0,max:6e5,onChange:e=>x({thinkTimeMs:e})}),(0,t.jsx)(u,{label:"Random extra (ms)",value:e.thinkJitterMs,min:0,max:6e5,onChange:e=>x({thinkJitterMs:e})})]}),(0,t.jsx)(i.LabeledInput,{label:"Graceful stop",mono:!0,value:e.gracefulStop,error:(0,d.durationError)(e.gracefulStop),onChange:e=>x({gracefulStop:e}),hint:"Time in-flight requests get to finish."})]}):null]})},"profileSummary",0,p],63343);var v=e.i(1675),g=e.i(80707);let j=null,y=null,k=new Set;function N(){return y??=fetch("/engine/local-servers",{cache:"no-store"}).then(e=>e.ok?e.json():null).then(e=>(e&&(j=e.servers),j)).catch(()=>j).finally(()=>{y=null,k.forEach(e=>e())}),k.forEach(e=>e()),y}var w=e.i(6278);let C=/^\{\{\s*([A-Za-z_][\w.-]*)\s*\}\}/,$=/^(https?):\/\/(localhost|127\.0\.0\.1)(?::(\d{1,5}))?(?=[/?#]|$)/i,S="\0none",E="\0local-other",q="apitestcenter-local-ports",R={GET:"text-ok",POST:"text-warn",PUT:"text-accent",PATCH:"text-accent",DELETE:"text-bad",HEAD:"text-mute",OPTIONS:"text-mute"};function T(){try{let e=JSON.parse(localStorage.getItem(q)??"[]");return(Array.isArray(e)?e.filter(e=>Number.isInteger(e)&&e>0&&e<65536):[]).slice(0,5)}catch{return[]}}function M(e){try{localStorage.setItem(q,JSON.stringify([e,...T().filter(t=>t!==e)].slice(0,5)))}catch{}}let L=(0,r.forwardRef)(function({draft:e,onChange:s,onImported:a,actions:l},i){let{vars:o,environments:c,activeEnv:u}=(0,w.useWorkspace)(),[m,h]=(0,r.useState)([]),[x,p]=(0,r.useState)(null),f=(0,r.useRef)(null);(0,r.useEffect)(()=>h(T()),[]),(0,r.useEffect)(()=>{x&&f.current?.focus()},[x]);let b=e.url,q=C.exec(b)?.[1],L=Object.entries(o).filter(([e,t])=>/^https?:\/\//i.test(t.trim())&&("practiceApi"!==e||q===e)),D=(()=>{let e=C.exec(b);if(e&&L.some(([t])=>t===e[1]))return{prefix:e[0],text:`{{${e[1]}}}`,value:e[1]};let t=$.exec(b);if(t){let e=t[1].toLowerCase(),s=t[3]??("https"===e?"443":"80");return{prefix:t[0],text:`${t[2]}${t[3]?`:${t[3]}`:""}`,value:`local:${e}:${s}`}}return null})(),P=b.startsWith("/"),z=P||""===b||null!=D,A=function(e){let[,t]=(0,r.useState)(0);(0,r.useEffect)(()=>{let e=()=>t(e=>e+1);return k.add(e),()=>void k.delete(e)},[]),(0,r.useEffect)(()=>{e&&null==j&&!y&&N()},[e]);let s=(0,r.useCallback)(()=>void N(),[]);return{servers:j??[],checked:null!=j,checking:null!=y,refresh:s}}(z),U=D?b.slice(D.prefix.length):b,O=e=>{let t=""===U||U.startsWith("/")||U.startsWith("?")?U:`/${U}`;return`${e}${t||(e.startsWith("{{")?"":"/")}`},F=A.servers,I=[...F.map(e=>({value:`local:${e.scheme}:${e.port}`,label:`localhost:${e.port}`,hint:[e.name,e.scheme,e.selfSigned?"self-signed":""].filter(Boolean).join(" · "),text:`localhost ${e.port} ${e.name??""}`,className:"font-mono",group:"local",inline:!0})),...m.filter(e=>!F.some(t=>t.port===e)).map(e=>({value:`local:http:${e}`,label:`localhost:${e}`,hint:A.checked?"used before · not running now":"used before",text:`localhost ${e}`,className:"font-mono text-mute",group:"local",inline:!0}))];D?.value.startsWith("local:")&&!I.some(e=>e.value===D.value)&&I.unshift({value:D.value,label:D.text,hint:"in this request",text:D.text,className:"font-mono",group:"local",inline:!0});let V=null!=D&&!D.value.startsWith("local:"),W=[...L.length?[{id:"env",label:u?.name??"Variables",text:u?.name??"variables",defaultOpen:V||null==D,action:c.length>1?{label:"switch",title:"Choose another environment",onClick:()=>setTimeout(()=>document.querySelector('button[role="combobox"][aria-label="Environment"]')?.click(),0)}:void 0}]:[],{id:"local",label:"Localhost",text:"localhost",hint:A.checking&&!A.checked?"checking…":`${F.length||"none"} running${A.checking?" · checking…":""}`,defaultOpen:!L.length&&null==D}],_=D?"text-accent":P?"text-warn":"text-mute";return(0,t.jsxs)("div",{className:"flex flex-wrap items-stretch gap-2",children:[(0,t.jsxs)("div",{className:"flex min-w-0 flex-[1_1_28rem] overflow-hidden rounded-lg border border-line bg-panel-2 focus-within:border-accent",children:[(0,t.jsx)(g.Select,{label:"Method",value:e.method,onChange:t=>s({...e,method:t}),options:d.METHODS.map(e=>({value:e,label:e,className:`font-mono font-medium ${R[e]}`})),minWidth:140,className:`shrink-0 border-r border-line px-3 font-mono text-sm font-medium outline-none focus-visible:bg-panel ${R[e.method]}`}),x?(0,t.jsxs)("form",{className:"flex shrink-0 items-center gap-1 border-r border-line px-2 font-mono text-xs",onSubmit:t=>{t.preventDefault(),(()=>{if(!x)return;let t=Number(x.port);!Number.isInteger(t)||t<1||t>65535||(M(t),h(T()),s((0,d.withUrl)(e,O(`${x.scheme}://localhost:${t}`))),p(null))})()},onKeyDown:e=>"Escape"===e.key&&p(null),children:[(0,t.jsx)("button",{type:"button",title:"Switch between http and https",onClick:()=>p({...x,scheme:"http"===x.scheme?"https":"http"}),className:"rounded px-1 text-accent hover:bg-panel",children:x.scheme}),(0,t.jsx)("span",{className:"text-mute",children:"://localhost:"}),(0,t.jsx)("input",{ref:f,value:x.port,onChange:e=>p({...x,port:e.target.value.replace(/\D/g,"").slice(0,5)}),inputMode:"numeric",placeholder:"8080","aria-label":"Port",className:"w-14 rounded border border-line bg-panel px-1.5 py-0.5 text-ink outline-none focus:border-accent"}),(0,t.jsx)("button",{type:"submit","aria-label":"Use this port",className:"rounded p-0.5 text-accent hover:bg-panel",children:(0,t.jsx)(v.Check,{size:14})}),(0,t.jsx)("button",{type:"button","aria-label":"Cancel",onClick:()=>p(null),className:"rounded p-0.5 text-mute hover:text-ink",children:(0,t.jsx)(n.X,{size:14})})]}):z?(0,t.jsx)(g.Select,{label:"Base URL",value:D?.value??S,onChange:t=>{if(t===E)return p({scheme:"http",port:""});if(t===S)return s((0,d.withUrl)(e,U));if(t.startsWith("local:")){let[,a,n]=t.split(":"),r=Number(n);return M(r),h(T()),s((0,d.withUrl)(e,O(`${a}://localhost:${r}`)))}s((0,d.withUrl)(e,O(`{{${t}}}`)))},onOpen:A.refresh,minWidth:320,buttonContent:D?.text??"Base URL",groups:W,options:[...L.map(([e,t])=>({value:e,label:`{{${e}}}`,hint:t,text:e,className:"font-mono text-accent",group:"env"})),...I,{value:E,label:"Another port…",text:"another port",group:"local"},{value:S,label:"No base URL — type the whole address",text:"no"}],className:`shrink-0 border-r border-line px-2.5 font-mono text-xs outline-none focus-visible:bg-panel ${_}`}):null,(0,t.jsx)("label",{className:"sr-only",htmlFor:"request-url",children:"Request URL"}),(0,t.jsx)("input",{ref:i,id:"request-url",value:U,spellCheck:!1,autoComplete:"off",onChange:t=>{let a=t.target.value,n=/^(https?:\/\/|\{\{)/i.test(a.trim())||""===U&&""!==a&&!/^[/?#]/.test(a);s((0,d.withUrl)(e,D&&!n?`${D.prefix}${a}`:a))},onPaste:t=>{let n=(0,d.withPaste)(e,t.clipboardData.getData("text"));n&&(t.preventDefault(),s(n.draft),n.note&&a?.(n.note))},placeholder:D?"/path — after the base URL":"Paste a URL or a curl command, or type a /path",className:"min-w-0 flex-1 bg-transparent px-3 py-2.5 font-mono text-sm text-ink outline-none placeholder:text-mute"})]}),(0,t.jsx)("div",{className:"flex shrink-0 gap-2",children:l})]})});e.s(["RequestBar",0,L],44794);var D=e.i(95486),P=e.i(99522);let z=(0,P.default)("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]);var A=e.i(89932),U=e.i(75117),O=e.i(88293);let F=(0,P.default)("wrap-text",[["path",{d:"m16 16-2 2 2 2",key:"kkc6pm"}],["path",{d:"M3 12h15a3 3 0 1 1 0 6h-4",key:"1cl7v7"}],["path",{d:"M3 18h7",key:"sq21v6"}],["path",{d:"M3 6h18",key:"d0wm0j"}]]);var I=e.i(13318),V=e.i(56396),W=e.i(15060),_=e.i(19656);let H={200:"OK",201:"Created",202:"Accepted",204:"No Content",301:"Moved Permanently",302:"Found",304:"Not Modified",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",408:"Request Timeout",409:"Conflict",415:"Unsupported Media Type",422:"Unprocessable Content",429:"Too Many Requests",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"};function B({label:e,value:s}){return(0,t.jsxs)("span",{className:"text-xs text-mute",children:[e," ",(0,t.jsx)("span",{className:"font-mono text-sm text-ink",children:s})]})}function K({message:e}){let s,{title:a,tip:n}=(s=e.toLowerCase()).includes("econnrefused")?{title:"Connection refused",tip:"Nothing is listening on that host and port. Is the server running, and is the port right?"}:s.includes("enotfound")||s.includes("eai_again")?{title:"Host not found",tip:"DNS could not resolve the host name. Check the spelling, or connect to the VPN for internal hosts."}:s.includes("timeout")||s.includes("etimedout")||s.includes("und_err_headers_timeout")?{title:"Timed out",tip:"The server did not answer in time. Raise Timeout under Settings, or check that the host is reachable."}:s.includes("certificate")||s.includes("self-signed")||s.includes("unable to verify")||s.includes("cert_")?{title:"TLS certificate rejected",tip:"The certificate is not trusted. For a lab certificate, turn on 'Skip TLS certificate check' under Settings."}:s.includes("econnreset")||s.includes("socket hang up")?{title:"Connection reset",tip:"The server closed the connection mid-request. Check the server logs, or a proxy or firewall in between."}:s.includes("engine")?{title:"Engine problem",tip:"The local engine did not answer. Make sure pnpm dev is running."}:{title:"Request failed",tip:"See the details below."};return(0,t.jsxs)("div",{role:"alert",className:"mt-3 rounded-md border border-bad/40 bg-bad/10 px-3 py-2.5",children:[(0,t.jsx)("p",{className:"text-sm font-medium text-bad",children:a}),(0,t.jsx)("p",{className:"mt-1 text-sm text-ink",children:n}),(0,t.jsx)("p",{className:"mt-2 font-mono text-xs break-all text-mute",children:e})]})}function J({headers:e}){let s=(0,V.useToast)(),a=Object.entries(e).sort(([e],[t])=>e.localeCompare(t));return 0===a.length?(0,t.jsx)("p",{className:"text-sm text-mute",children:"No headers."}):(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)("div",{className:"flex justify-end",children:(0,t.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 text-xs text-mute hover:text-ink",onClick:()=>{navigator.clipboard.writeText(a.map(([e,t])=>`${e}: ${t}`).join("\n")),s("Headers copied","success")},children:[(0,t.jsx)(A.Copy,{size:12})," Copy all"]})}),(0,t.jsx)("div",{className:"overflow-auto rounded-md border border-line",children:(0,t.jsx)("table",{className:"w-full text-left text-[13px]",children:(0,t.jsx)("tbody",{children:a.map(([e,s])=>(0,t.jsxs)("tr",{className:"border-t border-line first:border-t-0",children:[(0,t.jsx)("th",{scope:"row",className:"w-2/5 bg-panel-2 px-3 py-1.5 align-top font-mono font-normal text-mute",children:e}),(0,t.jsx)("td",{className:`px-3 py-1.5 font-mono break-all ${"[redacted]"===s?"text-mute italic":"text-ink"}`,children:s})]},e))})})}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"Cookie and authorization headers are redacted by the engine."})]})}function X({body:e,contentType:s,truncated:a,url:n}){let l=(0,V.useToast)(),i=function(e,t){let s=t.toLowerCase();if(s.includes("json"))return"json";if(s.includes("html"))return"html";if(s.includes("xml"))return"xml";let a=e.trim();if(a.startsWith("{")||a.startsWith("["))try{return JSON.parse(a),"json"}catch{}return/^<!doctype html|^<html/i.test(a)?"html":a.startsWith("<")?"xml":"text"}(e,s),d=a||e.length>=16384,[c,u]=(0,r.useState)("pretty"),[m,h]=(0,r.useState)(!0),[x,p]=(0,r.useState)(""),[f,b]=(0,r.useState)(0),[v,g]=(0,r.useState)(!1),j=(0,r.useRef)(null),y=(0,r.useRef)(null);(0,r.useEffect)(()=>{u("pretty"),p(""),b(0)},[e]);let k=(0,r.useMemo)(()=>e?"raw"===c?e:function(e,t){if("json"!==t)return e;try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}(e,i):"",[e,c,i]),N=(0,r.useMemo)(()=>(function(e,t){if(!t)return 0;let s=e.toLowerCase(),a=t.toLowerCase(),n=0;for(let e=s.indexOf(a);e>=0&&n<1e4;e=s.indexOf(a,e+a.length))n++;return n})(k,x),[k,x]);function w(e){0!==N&&b(t=>(t+e+N)%N)}(0,r.useEffect)(()=>{let e=y.current?.querySelector("mark.current");e?.scrollIntoView({block:"center"})},[f,x,c]);let C=[{value:"pretty",label:"Pretty"},{value:"raw",label:"Raw"},..."html"===i?[{value:"preview",label:"Preview"}]:[]];return e?(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border border-line bg-panel-2",onKeyDown:e=>{(e.ctrlKey||e.metaKey)&&"f"===e.key.toLowerCase()&&(e.preventDefault(),g(!0),window.setTimeout(()=>j.current?.focus(),0))},children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-line px-2 py-1.5",children:[(0,t.jsx)(o.Segmented,{label:"Body view",value:c,onChange:u,options:C}),(0,t.jsx)("span",{className:"rounded border border-line px-1.5 py-0.5 font-mono text-xs text-mute uppercase",children:i}),a?(0,t.jsx)("span",{className:"text-xs text-warn",children:"First 64 KB shown"}):null,(0,t.jsxs)("div",{className:"ml-auto flex items-center gap-1",children:[v?(0,t.jsxs)("div",{className:"flex items-center gap-1 rounded-md border border-line bg-panel px-1.5",children:[(0,t.jsx)(O.Search,{size:12,className:"text-mute"}),(0,t.jsx)("input",{ref:j,value:x,"aria-label":"Find in body",placeholder:"Find",onChange:e=>{p(e.target.value),b(0)},onKeyDown:e=>{"Enter"===e.key&&w(e.shiftKey?-1:1),"Escape"===e.key&&(p(""),g(!1))},className:"w-28 bg-transparent py-1 text-xs text-ink outline-none"}),(0,t.jsx)("span",{className:"font-mono text-xs text-mute tabular",children:x?`${N?f+1:0}/${N}`:""}),(0,t.jsx)(G,{label:"Previous match",onClick:()=>w(-1),children:(0,t.jsx)(z,{size:12})}),(0,t.jsx)(G,{label:"Next match",onClick:()=>w(1),children:(0,t.jsx)(D.ChevronDown,{size:12})})]}):(0,t.jsx)(G,{label:"Find in body (Ctrl+F)",onClick:()=>{g(!0),window.setTimeout(()=>j.current?.focus(),0)},children:(0,t.jsx)(O.Search,{size:14})}),(0,t.jsx)(G,{label:m?"Turn off line wrap":"Wrap long lines",pressed:m,onClick:()=>h(e=>!e),children:(0,t.jsx)(F,{size:14})}),(0,t.jsx)(G,{label:"Copy body",onClick:()=>{navigator.clipboard.writeText(k),l("Body copied","success")},children:(0,t.jsx)(A.Copy,{size:14})}),(0,t.jsx)(G,{label:"Download body",onClick:()=>{var e;return(0,W.downloadText)(function(e,t){let s="response";try{s=new URL(e).pathname.split("/").filter(Boolean).pop()||"response"}catch{}return`${s.replace(/[^\w.-]+/g,"_")}.${"json"===t?"json":"html"===t?"html":"xml"===t?"xml":"txt"}`}(n,i),k,"json"===(e=i)?"application/json":"html"===e?"text/html":"xml"===e?"application/xml":"text/plain")},children:(0,t.jsx)(U.Download,{size:14})})]})]}),"preview"===c?(0,t.jsx)("iframe",{title:"HTML preview",sandbox:"",srcDoc:e,className:"min-h-[24rem] w-full flex-1 bg-white"}):(0,t.jsx)("pre",{ref:y,tabIndex:0,"aria-label":"Response body",className:`min-h-[12rem] flex-1 overflow-auto p-3 font-mono text-[13px] leading-5 text-ink ${m?"break-words whitespace-pre-wrap":"whitespace-pre"}`,children:x?function(e,s,a){let n=[],r=e.toLowerCase(),l=s.toLowerCase(),i=0,o=0;for(let s=r.indexOf(l);s>=0&&o<1e4;s=r.indexOf(l,s+l.length))n.push(e.slice(i,s)),n.push((0,t.jsx)("mark",{className:`find-hit${o===a?" current":""}`,children:e.slice(s,s+l.length)},s)),i=s+l.length,o++;return n.push(e.slice(i)),n}(k,x,f):"pretty"!==c||"json"!==i||d?k:function(e){let s=[],a=0;for(let n of e.matchAll(Z)){let r=n.index??0;s.push(e.slice(a,r)),n[1]?(s.push((0,t.jsx)("span",{className:n[2]?"tok-key":"tok-str",children:n[1]},r)),n[2]&&s.push(n[2])):n[3]?s.push((0,t.jsx)("span",{className:"tok-lit",children:n[3]},r)):s.push((0,t.jsx)("span",{className:"tok-num",children:n[4]},r)),a=r+n[0].length}return s.push(e.slice(a)),s}(k)})]}):(0,t.jsx)("p",{className:"text-sm text-mute",children:"Empty body."})}function G({label:e,onClick:s,children:a,pressed:n}){return(0,t.jsx)("button",{type:"button","aria-label":e,title:e,"aria-pressed":n,onClick:s,className:`rounded p-1 hover:bg-panel hover:text-ink ${n?"text-accent":"text-mute"}`,children:a})}let Z=/("(?:\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*")(\s*:)?|\b(true|false|null)\b|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g;e.s(["ResponseViewer",0,function({result:e}){var s,a;let n,[l,i]=(0,r.useState)("body"),o=e.checks??[],d=o.filter(e=>e.ok).length,c=Object.keys(e.headers).length,u=(n=Object.keys(s=e.headers).find(e=>"content-type"===e.toLowerCase()))?s[n]??"":"",m=(0,r.useMemo)(()=>new TextEncoder().encode(e.body).length,[e.body]),h=!e.status;return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[(0,t.jsx)("span",{className:`rounded-md border px-2 py-0.5 font-mono text-sm font-medium ${(a=e.status)>=200&&a<300?"text-ok border-ok/40 bg-ok/10":a>=300&&a<400?"text-accent border-accent/40 bg-accent/10":a>=400&&a<500?"text-warn border-warn/40 bg-warn/10":"text-bad border-bad/40 bg-bad/10"}`,children:h?"Error":`${e.status} ${H[e.status]??""}`.trim()}),(0,t.jsx)(B,{label:"Time",value:`${e.durationMs} ms`}),h?null:(0,t.jsx)(B,{label:"Size",value:`${(0,_.formatBytes)(m)}${e.truncated?"+":""}`}),u?(0,t.jsx)(B,{label:"Type",value:u.split(";")[0]??u}):null,o.length?(0,t.jsxs)("button",{type:"button",onClick:()=>i("checks"),className:`rounded-md border px-2 py-0.5 text-xs ${d===o.length?"border-ok/40 text-ok":"border-bad/40 text-bad"}`,children:[d===o.length?"✓":"✕"," ",d,"/",o.length," checks"]}):null]}),(0,t.jsx)("p",{className:"mt-2 font-mono text-xs break-all text-mute",children:e.url}),e.setup||e.dataRow?(0,t.jsxs)("p",{className:"mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-mute",children:[e.setup?(0,t.jsxs)("span",{className:e.setup.ok?"":"text-bad",children:["Ran first: ",(0,t.jsx)("span",{className:"text-ink",children:e.setup.label}),e.setup.status?` \xb7 ${e.setup.status} \xb7 ${e.setup.durationMs} ms`:"",e.setup.values.map(e=>(0,t.jsxs)("span",{className:`ml-2 font-mono ${e.found?"text-ok":"text-bad"}`,title:e.found?`From ${e.from}: ${e.preview}`:`Not found: ${e.from}`,children:[e.found?"✓":"✕"," ",`{{${e.name}}}`]},e.name))]}):null,e.dataRow?(0,t.jsxs)("span",{children:["Test data: row ",e.dataRow.row," of ",e.dataRow.of.toLocaleString()]}):null]}):null,e.error?(0,t.jsx)(K,{message:e.error}):null,h?null:(0,t.jsxs)("div",{className:"mt-3 flex min-h-0 flex-1 flex-col",children:[(0,t.jsx)(I.Tabs,{id:"response",label:"Response",value:l,onChange:i,items:[{id:"body",label:"Body"},{id:"headers",label:"Headers",badge:c||void 0},...o.length?[{id:"checks",label:"Checks",badge:(0,t.jsxs)("span",{className:d===o.length?"text-ok":"text-bad",children:[d,"/",o.length]})}]:[]]}),(0,t.jsx)("div",{...(0,I.tabPanelProps)("response",l),className:"flex min-h-0 flex-1 flex-col pt-3",children:"body"===l?(0,t.jsx)(X,{body:e.body,contentType:u,truncated:e.truncated,url:e.url}):"checks"===l?(0,t.jsx)("ul",{className:"space-y-1.5",children:o.map((e,s)=>(0,t.jsxs)("li",{className:`flex items-center gap-2 rounded-md border px-3 py-2 text-sm ${e.ok?"border-ok/30 bg-ok/5":"border-bad/40 bg-bad/10"}`,children:[(0,t.jsx)("span",{className:e.ok?"text-ok":"text-bad","aria-hidden":!0,children:e.ok?"✓":"✕"}),(0,t.jsx)("span",{className:"font-mono text-[13px] text-ink",children:e.name}),(0,t.jsx)("span",{className:`ml-auto text-xs ${e.ok?"text-ok":"text-bad"}`,children:e.ok?"pass":"fail"})]},s))}):(0,t.jsx)(J,{headers:e.headers})})]})]})}],60566)},68228,65638,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(78451),a=e.i(89932),n=e.i(99522);let r=(0,n.default)("eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]),l=(0,n.default)("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]),i=(0,n.default)("lock",[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]);var o=e.i(71189),d=e.i(43514),c=e.i(96659),u=e.i(87283),m=e.i(83067),h=e.i(39170),x=e.i(80707),p=e.i(56396);e.i(42674);var f=e.i(5305),b=e.i(65238),v=e.i(6278);let g=()=>globalThis.crypto?.randomUUID?.()??`env-${Date.now().toString(36)}`;function j({onClose:e}){let s=(0,p.useToast)(),n=(0,h.useConfirm)(),{environments:r,activeEnv:l,setActiveEnv:d,saveEnvironments:x,index:f}=(0,v.useWorkspace)(),[b,k]=(0,m.useState)(()=>structuredClone(r)),[N,w]=(0,m.useState)(l?.id??r[0]?.id??null),[C,$]=(0,m.useState)(!1),S=(0,m.useRef)(null),E=b.find(e=>e.id===N)??null,q=JSON.stringify(b)!==JSON.stringify(r);(0,m.useEffect)(()=>{let e=document.activeElement;return S.current?.querySelector("input,button")?.focus(),()=>e?.focus()},[]);let R=(e,t)=>k(s=>s.map(s=>s.id===e?{...s,...t}:s));function T(e){let t=e?{id:g(),name:`${e.name} copy`,variables:structuredClone(e.variables)}:{id:g(),name:b.length?`Environment ${b.length+1}`:"DEV",variables:[{key:"baseUrl",value:"",secret:!1}]};k(e=>[...e,t]),w(t.id)}async function M(){(!q||await n({title:"Discard changes to environments?",confirmLabel:"Discard",tone:"danger"}))&&e()}async function L(){$(!0);try{await x(b),l&&!b.some(e=>e.id===l.id)&&d(null),s("Environments saved","success"),e()}catch(e){s(e instanceof Error?e.message:"Could not save environments","error")}finally{$(!1)}}return(0,t.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-black/50 p-4 backdrop-blur-sm",onMouseDown:e=>e.target===e.currentTarget&&void M(),children:(0,t.jsxs)("div",{ref:S,role:"dialog","aria-modal":"true","aria-label":"Environments",onKeyDown:e=>"Escape"===e.key&&void M(),className:"flex max-h-[85vh] w-full max-w-4xl flex-col overflow-hidden rounded-xl border border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-center justify-between border-b border-line px-5 py-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{className:"text-base font-medium text-ink",children:"Environments"}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Use ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"{{name}}"})," in the URL, params, headers, body, or auth. Saved to environments.json in your app-data folder."]})]}),(0,t.jsx)("button",{type:"button","aria-label":"Close",className:"rounded p-1 text-mute hover:text-ink",onClick:()=>void M(),children:(0,t.jsx)(u.X,{size:16})})]}),(0,t.jsxs)("div",{className:"grid min-h-0 flex-1 md:grid-cols-[14rem_minmax(0,1fr)]",children:[(0,t.jsxs)("nav",{"aria-label":"Environment list",className:"space-y-1 overflow-auto border-line p-3 md:border-r",children:[b.map(e=>(0,t.jsxs)("button",{type:"button",onClick:()=>w(e.id),"aria-current":e.id===N?"true":void 0,className:`block w-full truncate rounded-md px-2 py-1.5 text-left text-sm ${e.id===N?"bg-accent-dim text-ink":"text-mute hover:bg-panel-2 hover:text-ink"}`,children:[e.name,(0,t.jsx)("span",{className:"ml-1 text-xs text-mute",children:e.variables.length})]},e.id)),(0,t.jsxs)("button",{type:"button",onClick:()=>T(),className:"mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline",children:[(0,t.jsx)(o.Plus,{size:12,"aria-hidden":!0})," New environment"]})]}),(0,t.jsx)("section",{className:"min-h-0 overflow-auto p-4",children:E?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("label",{className:"min-w-0 flex-1",children:[(0,t.jsx)("span",{className:"sr-only",children:"Environment name"}),(0,t.jsx)("input",{value:E.name,onChange:e=>R(E.id,{name:e.target.value}),className:"input text-base font-medium"})]}),(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1.5 text-xs",onClick:()=>T(E),children:[(0,t.jsx)(a.Copy,{size:13})," Duplicate"]}),(0,t.jsxs)("button",{type:"button",className:"btn btn-danger py-1.5 text-xs",onClick:()=>{k(e=>e.filter(e=>e.id!==E.id)),w(b.find(e=>e.id!==E.id)?.id??null)},children:[(0,t.jsx)(c.Trash2,{size:13})," Delete"]})]}),(0,t.jsx)(y,{vars:E.variables,onPatch:(e,t)=>E&&R(E.id,{variables:E.variables.map((s,a)=>a===e?{...s,...t}:s)}),onChange:e=>R(E.id,{variables:e})}),(0,t.jsxs)("p",{className:"flex items-start gap-1.5 text-xs text-mute",children:[(0,t.jsx)(i,{size:12,className:"mt-0.5 shrink-0","aria-hidden":!0}),f?.secretsPersistent?"Secret values are encrypted on this computer and never written to environments.json.":"Secret values are never written to disk. In this browser setup they are kept by the engine until it restarts; the desktop app encrypts them."]})]}):(0,t.jsxs)("div",{className:"py-12 text-center text-sm text-mute",children:["No environments yet. Create one for each place you test — DEV, UAT, PROD.",(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsxs)("button",{type:"button",className:"btn btn-primary text-sm",onClick:()=>T(),children:[(0,t.jsx)(o.Plus,{size:14})," New environment"]})})]})})]}),(0,t.jsxs)("footer",{className:"flex justify-end gap-2 border-t border-line px-5 py-3",children:[(0,t.jsx)("button",{type:"button",className:"btn btn-secondary text-sm",onClick:()=>void M(),children:"Cancel"}),(0,t.jsx)("button",{type:"button",className:"btn btn-primary text-sm",disabled:!q||C,onClick:()=>void L(),children:"Save environments"})]})]})})}function y({vars:e,onPatch:s,onChange:a}){let[n,i]=(0,m.useState)(new Set),d=new Set(e.map(e=>e.key.trim()).filter((e,t,s)=>e&&s.indexOf(e)!==t));return(0,t.jsxs)("div",{className:"overflow-hidden rounded-md border border-line",children:[(0,t.jsxs)("div",{className:"grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_5.5rem_2rem] bg-panel-2 text-xs text-mute",children:[(0,t.jsx)("span",{className:"px-2.5 py-1.5",children:"Variable"}),(0,t.jsx)("span",{className:"border-l border-line px-2.5 py-1.5",children:"Value"}),(0,t.jsx)("span",{className:"border-l border-line px-2.5 py-1.5",children:"Secret"}),(0,t.jsx)("span",{})]}),e.map((o,c)=>{let m=o.key&&!/^[A-Za-z_][\w.-]*$/.test(o.key)||d.has(o.key.trim());return(0,t.jsxs)("div",{className:"grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_5.5rem_2rem] border-t border-line",children:[(0,t.jsx)("input",{"aria-label":`Variable ${c+1} name`,"aria-invalid":m||void 0,title:m?"Letters, digits, _ . - ; must start with a letter or _ ; must be unique":void 0,value:o.key,onChange:e=>s(c,{key:e.target.value}),placeholder:"baseUrl",className:`min-w-0 bg-transparent px-2.5 py-1.5 font-mono text-[13px] outline-none focus:bg-panel-2 ${m?"text-bad":"text-ink"}`}),(0,t.jsxs)("span",{className:"relative flex min-w-0 border-l border-line",children:[(0,t.jsx)("input",{"aria-label":`Variable ${c+1} value`,type:o.secret&&!n.has(c)?"password":"text",autoComplete:"off",value:o.value,onChange:e=>s(c,{value:e.target.value}),className:"min-w-0 flex-1 bg-transparent px-2.5 py-1.5 font-mono text-[13px] text-ink outline-none focus:bg-panel-2"}),o.secret?(0,t.jsx)("button",{type:"button","aria-label":n.has(c)?"Hide value":"Show value",onClick:()=>i(e=>{let t=new Set(e);return t.has(c)?t.delete(c):t.add(c),t}),className:"px-2 text-mute hover:text-ink",children:n.has(c)?(0,t.jsx)(l,{size:13}):(0,t.jsx)(r,{size:13})}):null]}),(0,t.jsxs)("label",{className:"flex items-center gap-1.5 border-l border-line px-2.5 text-xs text-mute",children:[(0,t.jsx)("input",{type:"checkbox",checked:o.secret,onChange:e=>s(c,{secret:e.target.checked}),className:"accent-[var(--accent)]"}),"secret"]}),(0,t.jsx)("button",{type:"button","aria-label":`Remove ${o.key||`variable ${c+1}`}`,onClick:()=>a(e.filter((e,t)=>t!==c)),className:"grid place-items-center text-mute hover:text-bad",children:(0,t.jsx)(u.X,{size:13})})]},c)}),(0,t.jsxs)("button",{type:"button",onClick:()=>a([...e,{key:"",value:"",secret:!1}]),className:"flex w-full items-center gap-1 border-t border-line px-2.5 py-1.5 text-xs text-accent hover:bg-panel-2",children:[(0,t.jsx)(o.Plus,{size:12,"aria-hidden":!0})," Add variable"]})]})}e.s(["EnvironmentBar",0,function({drafts:e,collections:a=[]}){let{environments:n,activeEnv:r,setActiveEnv:l,vars:i,savedValues:o,clearSavedValues:c}=(0,v.useWorkspace)(),u=Object.keys(o),[h,p]=(0,m.useState)(!1),g=(0,m.useMemo)(()=>{let t=new Set;for(let a of e){let e=new Set((0,f.draftRuntimeNames)(a)),n=[a.url,a.bodyText,a.token,a.username,a.password,a.apiValue,...a.params.map(e=>e.value),...a.headers.map(e=>e.value)].join(" ");(0,s.findVariables)(n).forEach(s=>!e.has(s)&&t.add(s))}return[...t]},[e]),y=(0,b.useFolderVarNames)(a),k=g.filter(e=>!(e in i)&&!y.has(e));return(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-xs",children:[(0,t.jsxs)("span",{className:"flex items-center gap-1.5 text-mute",children:["Environment",(0,t.jsx)(x.Select,{label:"Environment",value:r?.id??"",onChange:e=>l(e||null),minWidth:200,options:[{value:"",label:"None",hint:"Only built-in variables"},...n.map(e=>({value:e.id,label:e.name,hint:`${e.variables.length} variable${1===e.variables.length?"":"s"}`}))],className:"rounded-md border border-line bg-panel-2 px-2 py-1 text-xs text-ink hover:border-mute focus-visible:border-accent focus-visible:outline-none"})]}),(0,t.jsxs)("button",{type:"button",onClick:()=>p(!0),className:"inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-mute hover:text-ink",children:[(0,t.jsx)(d.Settings2,{size:12,"aria-hidden":!0})," Manage"]}),g.length>0?k.length?(0,t.jsxs)("span",{className:"text-warn",role:"status",children:[k.map(e=>`{{${e}}}`).join(", ")," not defined",r?` in ${r.name}`:" — pick an environment"]}):(0,t.jsxs)("span",{className:"text-mute",children:["Uses ",g.map(e=>`{{${e}}}`).join(", ")]}):null,u.length?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-mute",title:u.map(e=>`{{${e}}} — saved from “${o[e].from}”`).join("\n"),children:["Saved from answers: ",(0,t.jsx)("span",{className:"font-mono text-accent",children:u.map(e=>`{{${e}}}`).join(", ")}),(0,t.jsx)("button",{type:"button",onClick:c,className:"text-mute underline-offset-2 hover:text-ink hover:underline",children:"Clear"})]}):null,h?(0,t.jsx)(j,{onClose:()=>p(!1)}):null]})},"VariableTable",0,y],68228);var k=e.i(95486),N=e.i(60961);let w=(0,n.default)("file-plus-2",[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4",key:"1pf5j1"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M3 15h6",key:"4e2qda"}],["path",{d:"M6 12v6",key:"1u72j0"}]]),C=(0,n.default)("folder",[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]]),$=(0,n.default)("folder-plus",[["path",{d:"M12 10v6",key:"1bos4e"}],["path",{d:"M9 13h6",key:"1uhe8q"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]]),S=(0,n.default)("import",[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m8 11 4 4 4-4",key:"1dohi6"}],["path",{d:"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4",key:"1ywtjm"}]]);var E=e.i(19286),q=e.i(81538),R=e.i(3792),T=e.i(88293),M=e.i(50804),L=e.i(67217),D=e.i(41997),P=e.i(37837),z=e.i(27813),A=e.i(36e3),U=e.i(13318);function O({path:e,onClose:a}){let n=(0,p.useToast)(),{refresh:r}=(0,v.useWorkspace)(),[l,i]=(0,m.useState)(null),[o,d]=(0,m.useState)([]),[c,h]=(0,m.useState)([]),[x,f]=(0,m.useState)("auth"),[g,j]=(0,m.useState)(!1);async function k(){if(l&&!g){j(!0);try{await b.folderApi.save(e,{...l,headers:l.headers.filter(e=>e.key.trim()),variables:l.variables.filter(e=>e.key.trim())}),await r(),n(`Saved the settings of ${e}`,"success"),a()}catch(e){n(e instanceof Error?e.message:"Could not save","error")}finally{j(!1)}}}(0,m.useEffect)(()=>{let t=!0;return Promise.all([b.folderApi.get(e),b.folderApi.chain((0,s.parentFolder)(e))]).then(([e,s])=>{t&&(i(e.settings),d(e.secretsMissing??[]),h(s))}).catch(e=>{t&&(n(e instanceof Error?e.message:"Could not open the folder","error"),i((0,s.emptyFolderSettings)()))}),()=>{t=!1}},[e,n]);let N=[...c].reverse().find(e=>"inherit"!==e.settings.auth.authMode),w=l?{headers:l.headers.filter(e=>e.key.trim()).length,variables:l.variables.length}:{headers:0,variables:0};return(0,t.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-black/50 p-4 backdrop-blur-sm",onMouseDown:e=>e.target===e.currentTarget&&a(),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-labelledby":"folder-settings-title",onKeyDown:e=>"Escape"===e.key&&a(),className:"flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-xl border border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-start justify-between gap-3 border-b border-line px-5 py-3",children:[(0,t.jsxs)("div",{className:"min-w-0",children:[(0,t.jsxs)("h2",{id:"folder-settings-title",className:"truncate text-base font-medium text-ink",children:["Folder settings · ",e]}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"Every request inside — and inside its subfolders — uses these. A request's own value wins."})]}),(0,t.jsx)("button",{type:"button","aria-label":"Close",className:"rounded p-1 text-mute hover:text-ink",onClick:a,children:(0,t.jsx)(u.X,{size:16})})]}),l?(0,t.jsxs)("div",{className:"min-h-0 flex-1 overflow-auto px-5 py-4",children:[(0,t.jsx)(U.Tabs,{id:"folder-settings",label:"Folder settings",value:x,onChange:f,items:[{id:"auth",label:"Auth"},{id:"headers",label:"Headers",badge:w.headers||void 0},{id:"variables",label:"Variables",badge:w.variables||void 0}]}),(0,t.jsxs)("div",{...(0,U.tabPanelProps)("folder-settings",x),className:"pt-4",children:["auth"===x?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Requests set to ",(0,t.jsx)("span",{className:"text-ink",children:"Auth → From folder"})," (the default for new requests) use this — sign in once here instead of in every request."]}),(0,t.jsx)(D.AuthFields,{value:l.auth,onChange:e=>i({...l,auth:{...l.auth,...e}}),inheritLabel:"From parent",defaults:Object.fromEntries([...c.flatMap(e=>e.settings.variables),...l.variables].map(e=>[e.key,e.value])),inheritNote:N&&"none"!==N.settings.auth.authMode?(0,t.jsxs)(t.Fragment,{children:["Passes on the ",(0,t.jsx)("span",{className:"text-ink",children:(0,D.authModeLabel)(N.settings.auth.authMode)})," of"," ",(0,t.jsx)("span",{className:"text-ink",children:N.path}),"."]}):(0,t.jsx)(t.Fragment,{children:"No folder above sets auth, so this folder passes none down."}),secretNote:"Use {{token}} to take it from the environment, or type it — it's kept encrypted on this computer, never in the folder's file."}),o.some(e=>!e.startsWith("var:"))?(0,t.jsxs)("p",{className:"text-xs text-warn",children:["The saved ",o.filter(e=>!e.startsWith("var:")).join(", ")," isn't available on this computer — enter it again."]}):null]}):null,"headers"===x?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(A.KeyValueEditor,{rows:l.headers,onChange:e=>i({...l,headers:e}),keyPlaceholder:"Header",valuePlaceholder:"Value",noun:"header"}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"Sent with every request inside. An inner folder's or a request's header with the same name replaces it."})]}):null,"variables"===x?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(y,{vars:l.variables,onPatch:(e,t)=>i({...l,variables:l.variables.map((s,a)=>a===e?{...s,...t}:s)}),onChange:e=>i({...l,variables:e})}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Defaults for ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"{{name}}"})," in the requests inside. The chosen environment wins when it has the same name — so a folder can say"," ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"basePath = /v2"})," and the environment picks the server."]}),o.some(e=>e.startsWith("var:"))?(0,t.jsxs)("p",{className:"text-xs text-warn",children:["Secret values not available on this computer: ",o.filter(e=>e.startsWith("var:")).map(e=>e.slice(4)).join(", ")," — enter them again."]}):null]}):null]})]}):(0,t.jsx)("div",{className:"grid place-items-center p-10 text-mute",children:(0,t.jsx)(z.Loader2,{className:"animate-spin",size:18,"aria-label":"Loading"})}),(0,t.jsxs)("footer",{className:"flex justify-end gap-2 border-t border-line px-5 py-3",children:[(0,t.jsx)("button",{type:"button",className:"btn btn-secondary",onClick:a,disabled:g,children:"Cancel"}),(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",onClick:()=>void k(),disabled:!l||g,children:[g?(0,t.jsx)(z.Loader2,{size:14,className:"animate-spin"}):null,"Save folder settings"]})]})]})})}var F=e.i(14168);let I={GET:"text-ok",POST:"text-warn",PUT:"text-accent",PATCH:"text-accent",DELETE:"text-bad"};function V({activeId:e,onOpen:a,allowDelete:n=!0,newFolder:r,onNewFolderDone:l}){let i=(0,p.useToast)(),o=(0,h.useConfirm)(),{index:d,refresh:u}=(0,v.useWorkspace)(),[x,f]=(0,m.useState)(""),[g,j]=(0,m.useState)(new Set),[y,w]=(0,m.useState)(null),[$,S]=(0,m.useState)(null),q=d?.requests??[],P=d?.folders??[],z=x.trim().toLowerCase(),A=(0,m.useMemo)(()=>z?q.filter(e=>`${e.name} ${e.collection} ${e.url} ${e.method}`.toLowerCase().includes(z)):q,[q,z]),U=(0,m.useMemo)(()=>(function(e,t,a){let n={path:"",name:"",folders:[],requests:[],summary:null},r=new Map([["",n]]),l=e=>{let t=r.get(e);if(t)return t;let a={path:e,name:(0,s.folderName)(e),folders:[],requests:[],summary:null};return r.set(e,a),l((0,s.parentFolder)(e)).folders.push(a),a};if(a)for(let e of t)l(e.path);for(let t of e)l(t.collection).requests.push(t);for(let e of t){let t=r.get(e.path);t&&(t.summary=e)}let i=e=>{e.folders.sort((e,t)=>e.name.localeCompare(t.name)),e.folders.forEach(i)};return i(n),n})(A,P,!z),[A,P,z]);async function H(e){try{let t=await v.workspaceApi.get(e);a(t),t.secretsMissing?.length&&i(`Re-enter the ${t.secretsMissing.join(", ")} — secrets are kept only until the engine restarts in this setup`,"info")}catch(e){i(e instanceof Error?e.message:"Could not open the request","error")}}async function B(e){await o({title:`Delete “${e.name}”?`,body:"The saved request file is removed. Load test history is not affected.",confirmLabel:"Delete",tone:"danger"})&&(await v.workspaceApi.remove(e.id).catch(()=>void 0),await u())}async function K(e){if(w(null),l?.(),!y)return;let t=e.trim();if(t)try{if("new"===y.kind){let e=(0,s.folderPath)(y.parent?`${y.parent}/${t}`:t);await b.folderApi.save(e,(0,s.emptyFolderSettings)()),j(e=>{let t=new Set(e);return t.delete(y.parent),t})}else{let e=(0,s.folderPath)(t.includes("/")?t:(0,s.parentFolder)(y.path)?`${(0,s.parentFolder)(y.path)}/${t}`:t);e!==y.path&&await b.folderApi.move(y.path,e)}await u()}catch(e){i(e instanceof Error?e.message:"Could not do that","error")}}async function J(e){if(await o({title:`Delete the folder “${e}”?`,body:"Its settings and empty subfolders are removed. A folder that still has requests can't be deleted — move or delete them first.",confirmLabel:"Delete folder",tone:"danger"}))try{await b.folderApi.remove(e),await u()}catch(e){i(e instanceof Error?e.message:"Could not delete the folder","error")}}(0,m.useEffect)(()=>{r&&w({kind:"new",parent:""})},[r]);let X=s=>(0,t.jsx)("ul",{children:s.map(s=>(0,t.jsxs)("li",{className:`group flex items-center rounded ${s.id===e?"bg-accent-dim":"hover:bg-panel-2"}`,children:[(0,t.jsxs)("button",{type:"button",onClick:()=>void H(s.id),"aria-current":s.id===e?"true":void 0,title:s.url,className:"flex min-w-0 flex-1 items-center gap-2 px-1.5 py-1 text-left",children:[(0,t.jsx)("span",{className:`w-12 shrink-0 font-mono text-[11px] font-medium ${I[s.method]??"text-mute"}`,children:s.method}),(0,t.jsx)("span",{className:"min-w-0 truncate text-xs text-ink",children:s.name})]}),n?(0,t.jsx)("button",{type:"button","aria-label":`Delete ${s.name}`,onClick:()=>void B(s),className:"mr-1 rounded p-1 text-mute opacity-0 group-hover:opacity-100 hover:text-bad focus:opacity-100",children:(0,t.jsx)(c.Trash2,{size:12})}):null]},s.id))}),G=e=>{var s;let a=g.has(e.path)&&!z,r=(s=e.summary)?[s.auth?(0,D.authModeLabel)(s.auth):"",s.headers?`${s.headers} header${1===s.headers?"":"s"}`:"",s.variables?`${s.variables} variable${1===s.variables?"":"s"}`:""].filter(Boolean).join(" · "):"";return(0,t.jsxs)("div",{className:"mb-0.5",children:[y?.kind==="rename"&&y.path===e.path?(0,t.jsx)(W,{initial:e.path,label:`New name for ${e.path}`,onDone:e=>void K(e),hint:"Use / to move it into another folder"}):(0,t.jsxs)("div",{className:"group/folder flex items-center",children:[(0,t.jsxs)("button",{type:"button","aria-expanded":!a,onClick:()=>{let t;return t=e.path,j(e=>{let s=new Set(e);return s.has(t)?s.delete(t):s.add(t),s})},title:r?`Passes down: ${r}`:e.path,className:"flex min-w-0 flex-1 items-center gap-1 rounded px-1 py-1 text-left text-xs font-medium text-mute hover:text-ink",children:[a?(0,t.jsx)(N.ChevronRight,{size:12,"aria-hidden":!0,className:"shrink-0"}):(0,t.jsx)(k.ChevronDown,{size:12,"aria-hidden":!0,className:"shrink-0"}),(0,t.jsx)(C,{size:12,"aria-hidden":!0,className:"shrink-0"}),(0,t.jsx)("span",{className:"truncate",children:e.name}),e.summary?.auth?(0,t.jsx)(E.KeyRound,{size:11,className:"shrink-0 text-accent","aria-label":`signs in with ${(0,D.authModeLabel)(e.summary.auth)}`}):null,(0,t.jsx)("span",{className:"ml-auto pl-1 font-normal",children:function e(t){return t.requests.length+t.folders.reduce((t,s)=>t+e(s),0)}(e)})]}),n?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(M.default,{href:(0,F.suiteHref)(e.path),title:`Run all requests in ${e.path}`,"aria-label":`Run all requests in ${e.path}`,className:"ml-0.5 rounded p-1 text-mute opacity-0 group-hover/folder:opacity-100 hover:text-accent focus:opacity-100",children:(0,t.jsx)(R.Play,{size:12})}),(0,t.jsx)(_,{path:e.path,onSettings:()=>S(e.path),onNewInside:()=>w({kind:"new",parent:e.path}),onRename:()=>w({kind:"rename",path:e.path}),onDelete:()=>void J(e.path)})]}):null]}),a?null:(0,t.jsxs)("div",{className:"ml-3 border-l border-line/60 pl-1",children:[y?.kind==="new"&&y.parent===e.path?(0,t.jsx)(W,{initial:"",label:`New folder in ${e.path}`,onDone:e=>void K(e)}):null,e.folders.map(G),X(e.requests)]})]},e.path)};return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsxs)("label",{className:"relative mb-2 block",children:[(0,t.jsx)("span",{className:"sr-only",children:"Search saved requests"}),(0,t.jsx)(T.Search,{size:13,className:"pointer-events-none absolute top-1/2 left-2 -translate-y-1/2 text-mute","aria-hidden":!0}),(0,t.jsx)("input",{value:x,onChange:e=>f(e.target.value),placeholder:"Search requests",className:"input py-1 pl-7 text-xs"})]}),(0,t.jsxs)("div",{className:"min-h-0 flex-1 overflow-auto",children:[y?.kind==="new"&&""===y.parent?(0,t.jsx)(W,{initial:"",label:"New folder",onDone:e=>void K(e),hint:"Use / for a folder inside another: Orders/Admin"}):null,0===q.length&&0===P.length?(0,t.jsxs)("div",{className:"space-y-2 px-1 py-4 text-xs text-mute",children:[(0,t.jsx)("p",{children:"No saved requests yet. Press Save (Ctrl+S) to keep the current one."}),(0,t.jsxs)("p",{children:["Coming from Postman or Swagger?"," ",(0,t.jsx)("button",{type:"button",onClick:L.openImport,className:"text-accent hover:underline",children:"Import your requests"})]})]}):z&&0===A.length?(0,t.jsx)("p",{className:"px-1 py-4 text-xs text-mute",children:"Nothing matches."}):(0,t.jsxs)(t.Fragment,{children:[U.folders.map(G),X(U.requests)]})]}),$?(0,t.jsx)(O,{path:$,onClose:()=>S(null)}):null]})}function W({initial:e,label:s,onDone:a,hint:n}){let[r,l]=(0,m.useState)(e),i=(0,m.useRef)(null),o=(0,m.useRef)(!1);(0,m.useEffect)(()=>i.current?.select(),[]);let d=e=>{o.current||(o.current=!0,a(e))};return(0,t.jsxs)("div",{className:"px-1 py-1",children:[(0,t.jsx)("input",{ref:i,value:r,"aria-label":s,placeholder:"Folder name",onChange:e=>l(e.target.value),onKeyDown:e=>{"Enter"===e.key&&d(r),"Escape"===e.key&&d("")},onBlur:()=>d(r),className:"input py-1 text-xs"}),n?(0,t.jsx)("p",{className:"mt-0.5 text-[11px] text-mute",children:n}):null]})}function _({path:e,onSettings:s,onNewInside:a,onRename:n,onDelete:r}){let[l,i]=(0,m.useState)(!1),o=(0,m.useRef)(null),d=(e,s,a=!1)=>(0,t.jsx)("button",{type:"button",role:"menuitem",onClick:()=>{i(!1),s()},className:`block w-full rounded px-2.5 py-1.5 text-left text-sm hover:bg-panel-2 ${a?"text-bad":"text-ink"}`,children:e});return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("button",{ref:o,type:"button","aria-label":`Actions for ${e}`,"aria-haspopup":"menu","aria-expanded":l,onClick:()=>i(e=>!e),className:`rounded p-1 text-mute hover:text-ink focus:opacity-100 ${l?"opacity-100":"opacity-0 group-hover/folder:opacity-100"}`,children:(0,t.jsx)(q.MoreHorizontal,{size:13})}),(0,t.jsx)(P.Popover,{anchor:o,open:l,onClose:()=>i(!1),label:`Actions for ${e}`,width:220,role:"menu",children:(0,t.jsxs)("div",{className:"p-1",children:[d("Folder settings — auth, headers, variables",s),d("New folder inside",a),d("Rename or move",n),d("Delete folder",r,!0)]})})]})}e.s(["RequestPicker",0,function({onOpen:e}){let[s,a]=(0,m.useState)(!1),n=(0,m.useRef)(null);return(0,m.useEffect)(()=>{if(!s)return;let e=e=>!n.current?.contains(e.target)&&a(!1),t=e=>"Escape"===e.key&&a(!1);return document.addEventListener("pointerdown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("pointerdown",e),document.removeEventListener("keydown",t)}},[s]),(0,t.jsxs)("div",{ref:n,className:"relative",children:[(0,t.jsxs)("button",{type:"button","aria-expanded":s,onClick:()=>a(e=>!e),className:"inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-xs text-mute hover:text-ink",children:[(0,t.jsx)(C,{size:12,"aria-hidden":!0})," Load saved request"]}),s?(0,t.jsx)("div",{className:"absolute left-0 z-40 mt-1 flex h-80 w-80 flex-col rounded-md border border-line bg-panel p-2 shadow-xl",children:(0,t.jsx)(V,{allowDelete:!1,onOpen:t=>{e(t),a(!1)}})}):null]})},"RequestsPanel",0,function({activeId:e,onOpen:s,onNew:a,onClose:n}){let[r,l]=(0,m.useState)(!1);return(0,t.jsxs)("aside",{"aria-label":"Saved requests",className:"flex min-h-0 flex-col border-line px-3 py-4 lg:border-r",children:[(0,t.jsxs)("div",{className:"mb-2 flex items-center justify-between",children:[(0,t.jsx)("h2",{className:"text-xs font-medium tracking-wide text-mute uppercase",children:"Saved requests"}),(0,t.jsxs)("span",{className:"flex items-center gap-1",children:[(0,t.jsx)("button",{type:"button",onClick:a,title:"New request","aria-label":"New request",className:"rounded p-1 text-mute hover:bg-panel-2 hover:text-ink",children:(0,t.jsx)(w,{size:14})}),(0,t.jsx)("button",{type:"button",onClick:()=>l(!0),title:"New folder","aria-label":"New folder",className:"rounded p-1 text-mute hover:bg-panel-2 hover:text-ink",children:(0,t.jsx)($,{size:14})}),(0,t.jsx)("button",{type:"button",onClick:L.openImport,title:"Import from Postman or OpenAPI","aria-label":"Import from Postman or OpenAPI",className:"rounded p-1 text-mute hover:bg-panel-2 hover:text-ink",children:(0,t.jsx)(S,{size:14})}),(0,t.jsx)("button",{type:"button",onClick:n,title:"Hide saved requests","aria-label":"Hide saved requests",className:"rounded p-1 text-mute hover:bg-panel-2 hover:text-ink",children:(0,t.jsx)(u.X,{size:14})})]})]}),(0,t.jsx)(V,{activeId:e,onOpen:s,newFolder:r,onNewFolderDone:()=>l(!1)})]})},"SaveRequestForm",0,function({initial:e,onSave:s,onCancel:a}){let{index:n}=(0,v.useWorkspace)(),[r,l]=(0,m.useState)(e.name),[i,o]=(0,m.useState)(e.collection),d=(0,m.useRef)(null),c=[...new Set([...(n?.folders??[]).map(e=>e.path),...(n?.requests??[]).map(e=>e.collection)].filter(Boolean))].sort();return(0,m.useEffect)(()=>d.current?.select(),[]),(0,t.jsxs)("form",{onSubmit:e=>{e.preventDefault(),r.trim()&&s(r.trim(),i.trim())},onKeyDown:e=>"Escape"===e.key&&a(),className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("label",{className:"flex items-center gap-1.5 text-xs text-mute",children:["Name",(0,t.jsx)("input",{ref:d,value:r,onChange:e=>l(e.target.value),className:"input w-52 py-1 text-xs","aria-label":"Request name"})]}),(0,t.jsxs)("label",{className:"flex items-center gap-1.5 text-xs text-mute",children:["Collection",(0,t.jsx)("input",{value:i,onChange:e=>o(e.target.value),list:"atc-collections",placeholder:"none — or Orders/Admin",title:"A folder; use / for a folder inside another",className:"input w-48 py-1 text-xs","aria-label":"Collection"}),(0,t.jsx)("datalist",{id:"atc-collections",children:c.map(e=>(0,t.jsx)("option",{value:e},e))})]}),(0,t.jsx)("button",{type:"submit",className:"btn btn-primary py-1 text-xs",children:"Save request"}),(0,t.jsx)("button",{type:"button",className:"rounded p-1 text-mute hover:text-ink","aria-label":"Cancel",onClick:a,children:(0,t.jsx)(u.X,{size:14})})]})}],65638)},46679,e=>{"use strict";var t=e.i(65238),s=e.i(6278);e.i(42674);var a=e.i(5305);async function n(e,n,r,l){let i,o,d=n.before;if(!d)return e;try{i=await s.workspaceApi.get(d.requestId)}catch{throw Error(`Run first: “${d.requestName}” is no longer saved — pick another request on the Run first tab`)}if(i.secretsMissing?.length)throw Error(`Run first: the saved ${i.secretsMissing.join(", ")} of “${i.name}” is not available — open it and enter it again`);try{let e=await (0,t.withFolders)({...(0,a.requestFromUnknown)(i.request),before:null,testData:null},i.collection,r);o=(0,a.resolveDraft)(e.draft,e.vars,l)}catch(e){throw Error(`Run first “${i.name}”: ${e instanceof Error?e.message:"invalid request"}`)}try{return{...e,setup:(0,a.buildSetup)({...d,requestName:i.name},o)}}catch(e){throw Error(e instanceof Error&&e.message.startsWith("Run first")?e.message:`Run first “${i.name}”: ${e instanceof Error?e.message:"invalid request"}`)}}e.s(["withRunFirst",0,n])},21206,e=>{"use strict";e.i(24856);var t=e.i(59100);function s(e,t,a=0){return{ok:!1,status:a,statusText:"",headers:{},body:"",truncated:!1,durationMs:0,url:e,error:t}}async function a(e){let t=await e.text();try{return{json:JSON.parse(t),text:t}}catch{return{json:null,text:t}}}function n(e){return e.slice(0,180).replace(/\s+/g," ").trim()}async function r(e){let t=e.request.url;try{let r=await fetch("/engine/probe",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({request:e.request,auth:e.auth,options:e.options,setup:e.setup,data:e.data,save:e.save})}),{json:l,text:i}=await a(r);if(!l){let e=n(i);return s(t,e?`Engine error (${r.status}): ${e}`:`Engine error (${r.status}). Is it running?`,r.status)}if(!r.ok)return s(t,"string"==typeof l.error?l.error:"Request failed",r.status);return l}catch(e){return s(t,e instanceof Error?e.message:"Engine unreachable")}}async function l(e){let t=await fetch("/engine/runs",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),{json:s,text:r}=await a(t);if(!s)throw Error(n(r)||"Failed to start load");if(!t.ok)throw Error("string"==typeof s.error?s.error:"Failed to start load");return s}async function i(e){try{let t=await fetch(`/engine/runs/${e}`,{cache:"no-store"});if(!t.ok)return null;return await t.json()}catch{return null}}async function o(e){try{let t=await fetch(`/engine/runs/${e}/stop`,{method:"POST"});if(!t.ok)return null;return await t.json()}catch{return null}}let d=new Set(["completed","failed","cancelled","interrupted"]);e.s(["fetchRun",0,i,"hostOf",0,function(e){try{return new URL(e).host}catch{return e}},"isSuccess",0,function(e){return!!(e&&e.ok&&e.status>=200&&e.status<300)},"isTerminalStatus",0,function(e){return d.has(e)},"needsLoadConfirm",0,function(e,s,a){if(function(e){try{let t=new URL(e).hostname.toLowerCase();return"localhost"===t||"127.0.0.1"===t||"[::1]"===t||"::1"===t||t.endsWith(".localhost")}catch{return!1}}(a))return!1;if("stress"===e||"spike"===e||"soak"===e)return!0;let n=(0,t.isArrivalRate)(s.executor)?s.rate??Math.max(0,...s.stages.map(e=>e.target)):null;return null!=n?n>=50:((0,t.isArrivalRate)(s.executor)?s.maxVUs??s.vus:s.stages.length>0?Math.max(s.vus,...s.stages.map(e=>e.target)):s.vus)>=25},"sendRequest",0,r,"startLoadRun",0,l,"stopLoadRun",0,o])}]);
|