apitestcenter 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD-PARTY-NOTICES-UI.txt +1 -1
- package/dist/THIRD-PARTY-NOTICES.txt +1 -1
- package/dist/cli.mjs +564 -170
- package/dist/ui/404/index.html +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/__next.__PAGE__.txt +15 -14
- package/dist/ui/__next._full.txt +13 -12
- package/dist/ui/__next._tree.txt +2 -2
- package/dist/ui/_next/static/chunks/{2od90u8fd_sla.js → 0f9cyrqzolhzx.js} +1 -1
- package/dist/ui/_next/static/chunks/0imlzn2evcfw6.css +3 -0
- package/dist/ui/_next/static/chunks/{13xdai3-mkg7c.js → 1-ogjtk9dipfq.js} +319 -134
- package/dist/ui/_next/static/chunks/{2idsynwg5lkk7.js → 115l_disvbdxa.js} +1 -1
- package/dist/ui/_next/static/chunks/{36lx6-56-udwb.js → 1b31b8g5_5h-y.js} +1 -1
- package/dist/ui/_next/static/chunks/2qchu_7euauai.js +1 -0
- package/dist/ui/_next/static/chunks/{3ad2zh-p8_xhv.js → 2sa_fr4vgkkrp.js} +2 -2
- package/dist/ui/_next/static/chunks/{02myfb0nlri-z.js → 3jywp_61ylz0z.js} +1 -1
- package/dist/ui/_next/static/media/icon.1oy4kb0w-k_2v.png +0 -0
- package/dist/ui/_not-found/__next._full.txt +12 -11
- package/dist/ui/_not-found/__next._not-found.__PAGE__.txt +17 -16
- 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 +12 -11
- package/dist/ui/compare/__next._full.txt +13 -12
- package/dist/ui/compare/__next._tree.txt +2 -2
- package/dist/ui/compare/__next.compare.__PAGE__.txt +18 -17
- package/dist/ui/compare/index.html +1 -1
- package/dist/ui/compare/index.txt +13 -12
- package/dist/ui/history/__next._full.txt +14 -13
- package/dist/ui/history/__next._tree.txt +2 -2
- package/dist/ui/history/__next.history.__PAGE__.txt +19 -18
- package/dist/ui/history/index.html +1 -1
- package/dist/ui/history/index.txt +14 -13
- package/dist/ui/icon.png +0 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/index.txt +13 -12
- package/dist/ui/preview/__next._full.txt +14 -13
- package/dist/ui/preview/__next._tree.txt +2 -2
- package/dist/ui/preview/__next.preview.__PAGE__.txt +19 -18
- package/dist/ui/preview/index.html +1 -1
- package/dist/ui/preview/index.txt +14 -13
- package/dist/ui/suite/__next._full.txt +13 -12
- package/dist/ui/suite/__next._tree.txt +2 -2
- package/dist/ui/suite/__next.suite.__PAGE__.txt +18 -17
- package/dist/ui/suite/index.html +1 -1
- package/dist/ui/suite/index.txt +13 -12
- package/dist/ui/tests/__next._full.txt +12 -11
- package/dist/ui/tests/__next._tree.txt +2 -2
- package/dist/ui/tests/__next.tests.__PAGE__.txt +17 -16
- package/dist/ui/tests/index.html +1 -1
- package/dist/ui/tests/index.txt +12 -11
- package/package.json +1 -1
- package/dist/ui/_next/static/chunks/2i7s5kuurlkr6.css +0 -3
- package/dist/ui/_next/static/chunks/2nxnxp6p-40kg.js +0 -1
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_buildManifest.js +0 -0
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_clientMiddlewareManifest.js +0 -0
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_ssgManifest.js +0 -0
|
@@ -48,4 +48,4 @@
|
|
|
48
48
|
${u}
|
|
49
49
|
<Relationship Id="rId${c.length+1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
|
50
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)}]);
|
|
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,lastBody:R[eK.id]?.body,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,2 +1,2 @@
|
|
|
1
1
|
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,6980,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(90870),a=e.i(2385),n=e.i(95486),r=e.i(20621),l=e.i(27813),i=e.i(99522);let o=(0,i.default)("maximize-2",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"m21 3-7 7",key:"1l2asr"}],["path",{d:"m3 21 7-7",key:"tjx5ai"}],["path",{d:"M9 21H3v-6",key:"wtvkvv"}]]),c=(0,i.default)("minimize-2",[["path",{d:"m14 10 7-7",key:"oa77jy"}],["path",{d:"M20 10h-6V4",key:"mjg0md"}],["path",{d:"m3 21 7-7",key:"tjx5ai"}],["path",{d:"M4 14h6v6",key:"rmj7iw"}]]);var d=e.i(3792);let u=(0,i.default)("save",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);var m=e.i(50962),p=e.i(66478),h=e.i(83067),x=e.i(63343),f=e.i(44794),b=e.i(31753),g=e.i(29724),y=e.i(60566),v=e.i(39170),w=e.i(13318),j=e.i(68228),k=e.i(59100);let N=(0,i.default)("link-2",[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]]);var S=e.i(87283),E=e.i(80707),R=e.i(56396);e.i(42674);var q=e.i(5305),C=e.i(6278);let U="\0new";function $(e,t){if(!t.has("baseUrl"))return"baseUrl";let s="api";try{s=new URL(e).hostname.split(".")[0].replace(/[^A-Za-z0-9]/g,"")||"api"}catch{}let a=`${s}Url`;for(let e=2;t.has(a);e++)a=`${s}Url${e}`;return a}function L({draft:e,sent:s,onChange:a}){let{environments:n,activeEnv:r,vars:l}=(0,C.useWorkspace)(),[i,o]=(0,h.useState)(!1),c=function(e){try{let t=new URL(e);if(!/^https?:$/.test(t.protocol)||["localhost","127.0.0.1"].includes(t.hostname))return[];let s=t.origin,a=t.pathname.split("/").filter(Boolean);return a.length>=2?[s,`${s}/${a[0]}`]:[s]}catch{return[]}}(e.url),d=new Set(Object.values(l).map(e=>e.trim().replace(/\/+$/,"")));return!s||!c.length||c.some(e=>d.has(e))?null:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{type:"button",onClick:()=>o(!0),className:"inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-accent hover:underline",title:"Keep this server address in an environment",children:[(0,t.jsx)(N,{size:13,"aria-hidden":!0})," Save ",c[0].replace(/^https?:\/\//,"")," as a base URL"]}),i?(0,t.jsx)(P,{draft:e,addresses:c,environments:n,activeEnvId:r?.id??null,onChange:a,onClose:()=>o(!1)}):null]})}function P({draft:e,addresses:s,environments:a,activeEnvId:n,onChange:r,onClose:l}){let i=(0,R.useToast)(),{index:o,saveEnvironments:c,setActiveEnv:d,refresh:u}=(0,C.useWorkspace)(),[m,p]=(0,h.useState)(s[0]),[x,f]=(0,h.useState)(n??a[0]?.id??U),[b,g]=(0,h.useState)(()=>{try{return new URL(s[0]).hostname.split(".").slice(0,2).join(" ")}catch{return"My API"}}),y=a.find(e=>e.id===x)??null,v=(0,h.useMemo)(()=>new Set((y?.variables??[]).map(e=>e.key)),[y]),[w,j]=(0,h.useState)(()=>$(s[0],v)),[N,L]=(0,h.useState)(!0),[T,O]=(0,h.useState)(!1),A=(0,h.useRef)(null);(0,h.useEffect)(()=>A.current?.focus(),[]),(0,h.useEffect)(()=>j($(m,v)),[m,v]);let F=(o?.requests??[]).filter(t=>t.url.startsWith(m)&&t.url!==e.url),I=y?.variables.find(e=>e.key===w),M=k.VARIABLE_NAME.test(w)&&(x!==U||b.trim());async function z(){if(M&&!T){O(!0);try{let t=x===U?globalThis.crypto?.randomUUID?.()??`env-${Date.now().toString(36)}`:x,s=structuredClone(a),n=s.find(e=>e.id===t);n||(n={id:t,name:b.trim(),variables:[]},s.push(n)),n.variables=[...n.variables.filter(e=>e.key!==w),{key:w,value:m,secret:!1}],await c(s),d(t),r((0,q.withUrl)(e,`{{${w}}}${e.url.slice(m.length)}`));let o=0,p=0;if(N){for(let e of F){let t=await C.workspaceApi.get(e.id).catch(()=>null);if(!t||t.secretsMissing?.length){p++;continue}let s=(0,q.requestFromUnknown)(t.request);s.url.startsWith(m)&&(await C.workspaceApi.update(e.id,{name:t.name,collection:t.collection,request:(0,q.withUrl)(s,`{{${w}}}${s.url.slice(m.length)}`)}),o++)}await u()}i(`Saved {{${w}}} in ${n.name}.${o?` ${o} other saved request${1===o?"":"s"} now use it.`:""}${p?` ${p} left as they were (a saved secret isn't available).`:""} Save this request to keep the change.`,"success"),l()}catch(e){i(e instanceof Error?e.message:"Could not save the base URL","error")}finally{O(!1)}}}return(0,t.jsx)("div",{className:"fixed inset-0 z-[75] flex items-start justify-center overflow-y-auto bg-black/50 p-4 sm:p-16",role:"presentation",onMouseDown:e=>e.target===e.currentTarget&&!T&&l(),children:(0,t.jsxs)("form",{role:"dialog","aria-modal":"true","aria-labelledby":"save-base-title",onSubmit:e=>{e.preventDefault(),z()},onKeyDown:e=>"Escape"===e.key&&!T&&l(),className:"w-full max-w-lg space-y-4 rounded-xl border border-line bg-panel p-5 shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-center gap-2",children:[(0,t.jsx)("h2",{id:"save-base-title",className:"text-base font-medium text-ink",children:"Save as a base URL"}),(0,t.jsx)("button",{type:"button",onClick:l,"aria-label":"Close",className:"ml-auto rounded p-1 text-mute hover:text-ink",children:(0,t.jsx)(S.X,{size:16})})]}),(0,t.jsx)("p",{className:"text-sm text-mute",children:"Keep the server address in an environment, so you type only the path — and switch servers (UAT, Prod) by switching environments."}),(0,t.jsxs)("fieldset",{className:"space-y-1.5",children:[(0,t.jsx)("legend",{className:"mb-1 text-xs text-mute",children:"Address"}),s.map(e=>(0,t.jsxs)("label",{className:"flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)("input",{type:"radio",name:"address",checked:m===e,onChange:()=>p(e)}),(0,t.jsx)("span",{className:"font-mono text-xs break-all",children:e})]},e))]}),(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-mute",children:["Environment",(0,t.jsx)(E.Select,{label:"Environment",value:x,onChange:f,options:[...a.map(e=>({value:e.id,label:e.name,hint:`${e.variables.length} variables`})),{value:U,label:"New environment…"}],className:"rounded-md border border-line bg-panel-2 px-2 py-1.5 text-sm text-ink"})]}),(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-mute",children:["Variable name",(0,t.jsx)("input",{ref:A,value:w,onChange:e=>j(e.target.value.replace(/[^\w.-]/g,"")),className:"input py-1.5 font-mono text-sm"})]}),x===U?(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-mute sm:col-span-2",children:["New environment name",(0,t.jsx)("input",{value:b,onChange:e=>g(e.target.value),className:"input py-1.5 text-sm"})]}):null]}),I&&I.value!==m?(0,t.jsxs)("p",{className:"text-xs text-warn",children:[`{{${w}}}`," already exists in this environment (",I.value,") — it will be replaced."]}):null,(0,t.jsxs)("p",{className:"rounded-md bg-panel-2 px-3 py-2 font-mono text-xs text-ink break-all",children:[`{{${w}}}`,(0,t.jsx)("span",{className:"text-mute",children:e.url.slice(m.length)||"/"})]}),F.length?(0,t.jsxs)("label",{className:"flex items-start gap-2 text-sm text-ink",children:[(0,t.jsx)("input",{type:"checkbox",checked:N,onChange:e=>L(e.target.checked),className:"mt-1"}),(0,t.jsxs)("span",{children:["Also switch ",F.length," other saved request",1===F.length?"":"s"," that use this address",(0,t.jsxs)("span",{className:"block text-xs text-mute",children:[F.slice(0,3).map(e=>e.name).join(", "),F.length>3?` and ${F.length-3} more`:""]})]})]}):null,(0,t.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,t.jsx)("button",{type:"button",className:"btn btn-secondary",onClick:l,disabled:T,children:"Cancel"}),(0,t.jsx)("button",{type:"submit",className:"btn btn-primary",disabled:!M||T,children:"Save base URL"})]})]})})}var T=e.i(65638),O=e.i(21206),A=e.i(20054);let F="apitestcenter-lab-draft";var I=e.i(59180),M=e.i(88153),z=e.i(2603),D=e.i(46679),_=e.i(65238),V=e.i(727),B=e.i(45672),H=e.i(69578);let J="apitestcenter-lab-saved",W="apitestcenter-requests-panel",K="apitestcenter-last-run";function Q(e){try{sessionStorage.setItem(K,e)}catch{}}function Y(){return(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:[(0,t.jsxs)("span",{className:"relative flex h-2 w-2",children:[(0,t.jsx)("span",{className:"absolute inline-flex h-full w-full animate-ping rounded-full bg-accent opacity-60"}),(0,t.jsx)("span",{className:"relative inline-flex h-2 w-2 rounded-full bg-accent"})]}),"Load running"]})}function G({title:e,lines:s,action:a}){return(0,t.jsxs)("div",{className:"flex flex-1 flex-col items-center justify-center rounded-lg border border-dashed border-line px-6 py-14 text-center",children:[(0,t.jsx)("h2",{className:"text-base font-medium text-ink",children:e}),(0,t.jsx)("div",{className:"mt-2 max-w-md space-y-1.5 text-sm text-mute",children:s.map((e,s)=>(0,t.jsx)("p",{children:e},s))}),a?(0,t.jsx)("div",{className:"mt-5",children:a}):null]})}function X({runs:e,current:s,disabled:r,onPick:l}){let{slo:i}=(0,M.useSlo)(),[o,c]=(0,h.useState)(!1),d=(0,h.useRef)(null),u=(0,h.useMemo)(()=>e.slice(0,30),[e]);return(0,h.useEffect)(()=>{if(!o)return;let e=e=>{d.current?.contains(e.target)||c(!1)},t=e=>"Escape"===e.key&&c(!1);return document.addEventListener("pointerdown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("pointerdown",e),document.removeEventListener("keydown",t)}},[o]),(0,t.jsxs)("div",{ref:d,className:"relative",children:[(0,t.jsxs)("button",{type:"button",disabled:r,"aria-haspopup":"listbox","aria-expanded":o,onClick:()=>c(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:["Recent runs",(0,t.jsx)(n.ChevronDown,{size:12})]}),o?(0,t.jsx)("ul",{role:"listbox","aria-label":"Recent runs",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:u.map(e=>{let n=(0,a.buildVerdictFromInputs)(e.verdict,{slo:i}).overall,r=s?.id===e.id;return(0,t.jsx)("li",{role:"option","aria-selected":r,children:(0,t.jsxs)("button",{type:"button",onClick:()=>{l(e),c(!1)},className:`flex w-full items-center justify-between gap-2 rounded px-2 py-1.5 text-left text-xs ${r?"bg-accent-dim text-ink":"text-ink hover:bg-panel-2"}`,children:[(0,t.jsxs)("span",{className:"min-w-0 truncate",children:[e.baseline?(0,t.jsx)("span",{className:"mr-1 text-accent",title:"Baseline",children:"◆"}):null,e.name]}),(0,t.jsx)(Z,{level:n})]})},e.id)})}):null]})}function Z({level:e}){let s="pass"===e?"text-ok":"fail"===e?"text-bad":"text-warn";return(0,t.jsxs)("span",{className:`shrink-0 font-mono text-xs uppercase ${s}`,children:[(0,t.jsxs)("span",{"aria-hidden":!0,children:["pass"===e?"✓":"fail"===e?"✕":"!"," "]}),e]})}function ee(){let{slo:e,setSlo:s,ready:a}=(0,M.useSlo)(),[n,r]=(0,h.useState)(!1),[l,i]=(0,h.useState)(500),[o,c]=(0,h.useState)(0),[d,u]=(0,h.useState)(1),[m,p]=(0,h.useState)(99),[x,f]=(0,h.useState)(!1),b=(0,h.useRef)(!1);function g(e){let t={on:n,p95:l,p99:o,errPct:d,checksPct:m,abort:x,...e};if(r(t.on),i(t.p95),c(t.p99),u(t.errPct),p(t.checksPct),f(t.abort),!t.on||!(t.p95>0)||t.errPct<0)return s(null);s({p95Ms:t.p95,errorRate:t.errPct/100,p99Ms:t.p99>0?t.p99:void 0,checksRate:Math.min(100,Math.max(0,t.checksPct))/100,abortOnFail:t.abort})}(0,h.useEffect)(()=>{a&&!b.current&&(b.current=!0,e&&(r(!0),i(e.p95Ms),c(e.p99Ms??0),u(Number((100*e.errorRate).toFixed(4))),p(null!=e.checksRate?Number((100*e.checksRate).toFixed(2)):99),f(!0===e.abortOnFail)))},[a,e]);let y=(e,s,a,n)=>(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:e}),(0,t.jsx)("input",{type:"number",min:n.min,max:n.max,step:n.step,value:s,onChange:e=>g({[a]:Number(e.target.value)}),className:"input font-mono"}),n.hint?(0,t.jsx)("span",{className:"mt-1 block text-xs text-mute",children:n.hint}):null]});return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsx)("p",{className:"text-sm text-mute",children:"Targets decide whether a load test passes. They are sent to k6 as thresholds, drive the verdict and the report colours, and are remembered on this computer."}),(0,t.jsxs)("label",{className:"flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)("input",{type:"checkbox",checked:n,onChange:e=>g({on:e.target.checked}),className:"accent-[var(--accent)]"}),"Use my own performance targets"]}),n?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-3",children:[y("p95 must stay under (ms)",l,"p95",{min:1}),y("p99 must stay under (ms)",o,"p99",{min:0,hint:"0 = no p99 target"}),y("Error rate must stay under (%)",d,"errPct",{min:0,max:100,step:.1}),y("Checks must pass at least (%)",m,"checksPct",{min:0,max:100,step:.1,hint:"Only used when the request has checks"})]}),(0,t.jsxs)("label",{className:"flex items-start gap-2 rounded-md border border-line px-3 py-2.5 text-sm text-ink",children:[(0,t.jsx)("input",{type:"checkbox",checked:x,onChange:e=>g({abort:e.target.checked}),className:"mt-0.5 accent-[var(--accent)]"}),(0,t.jsxs)("span",{children:["Stop the test early if a target is clearly missed",(0,t.jsx)("span",{className:"block text-xs text-mute",children:"After a 10-second warm-up, k6 ends the run as soon as a target fails — saves time and stops hammering a struggling API."})]})]})]}):(0,t.jsx)("p",{className:"rounded-md bg-panel-2 px-3 py-2 text-sm text-mute",children:"Using built-in defaults: warn at p95 ≥ 500 ms or errors ≥ 1%, fail at p95 ≥ 2 s or errors ≥ 5%. No thresholds are sent to k6."})]})}e.s(["LabPage",0,function(){let e=(0,R.useToast)(),n=(0,v.useConfirm)(),i=(0,A.useEngineHealth)(),k=(0,z.useModKey)(),{slo:N}=(0,M.useSlo)(),{vars:S,activeEnv:E,refresh:U,rememberValues:$}=(0,C.useWorkspace)(),[P,Z]=(0,h.useState)(null),[et,es]=(0,h.useState)(!1),[ea,en]=(0,h.useState)(!0),er=(0,h.useRef)(null),[el,ei]=(0,h.useState)(q.defaultRequestDraft),[eo,ec]=(0,h.useState)(q.DEFAULT_LOAD),[ed,eu]=(0,h.useState)(!1),[em,ep]=(0,h.useState)(null),[eh,ex]=(0,h.useState)(!1),[ef,eb]=(0,h.useState)(!1),[eg,ey]=(0,h.useState)(!1),[ev,ew]=(0,h.useState)(null),[ej,ek]=(0,h.useState)(null),{index:eN,refresh:eS}=(0,I.useHistory)(),eE=eN?.runs??[],[eR,eq]=(0,h.useState)("response"),[eC,eU]=(0,h.useState)(!1),e$=ej?.status==="running"||ej?.status==="queued",eL=(0,q.isReady)(el),eP=(0,q.loadProblem)(eo),eT=eh||ef;(0,h.useEffect)(()=>{let e=null;try{e=sessionStorage.getItem(K)}catch{}e&&(0,O.fetchRun)(e).then(async t=>{if(t)return ek(t);let s=await I.historyApi.run(e).catch(()=>null);s&&ek({id:s.report.id,status:s.report.status,report:s.report})});let t=function(){try{let e=sessionStorage.getItem(F);if(!e)return null;let t=JSON.parse(e);if(2===t.v)return{request:(0,q.requestFromUnknown)(t.request),load:(0,q.loadFromUnknown)(t.load)};return{request:(0,q.requestFromUnknown)(t),load:(0,q.loadFromUnknown)(t)}}catch{return null}}();t&&(ei(t.request),ec(t.load));try{let e=sessionStorage.getItem(J);e&&Z(JSON.parse(e)),en("closed"!==localStorage.getItem(W))}catch{}eu(!0)},[]),(0,h.useEffect)(()=>{if(!ed)return;let e=window.setTimeout(()=>(function(e){try{sessionStorage.setItem(F,JSON.stringify({v:2,...e}))}catch{}})({request:el,load:eo}),250);return()=>window.clearTimeout(e)},[el,eo,ed]),(0,h.useEffect)(()=>{if(!ej||!e$)return;let t=!1,s=window.setInterval(async()=>{let s=await (0,O.fetchRun)(ej.id);if(s&&!t&&(ek(s),(0,O.isTerminalStatus)(s.status))){eS();let t="completed"===s.status?"finished":s.status;e(`Load test ${t}`,"failed"===s.status?"error":"success");let n=(0,a.buildVerdict)(s.report,{slo:N});(0,V.notifyFinished)({title:`Load test ${t}`,body:`${s.report.testName}
|
|
2
|
-
${"completed"===s.status?n.headline:s.error??"See the report for details."}`,ok:"completed"===s.status&&"fail"!==n.overall})}},500);return()=>{t=!0,window.clearInterval(s)}},[ej?.id,e$]);let eO=!!P&&JSON.stringify(el)!==P.snapshot;function eA(e){Z(e);try{e?sessionStorage.setItem(J,JSON.stringify(e)):sessionStorage.removeItem(J)}catch{}}function eF(e){en(e);try{localStorage.setItem(W,e?"open":"closed")}catch{}}async function eI(t){try{let s={name:t?.name??P.name,collection:t?.collection??P.collection,request:el},a=P&&!t?await C.workspaceApi.update(P.id,s):await C.workspaceApi.create(s);eA({id:a.id,name:a.name,collection:a.collection,snapshot:JSON.stringify(el)}),es(!1),await U(),e(`Saved “${a.name}”${a.collection?` in ${a.collection}`:""}`,"success")}catch(t){e(t instanceof Error?t.message:"Could not save the request","error")}}async function eM(){return!eO||n({title:`Discard changes to “${P.name}”?`,body:"They have not been saved.",confirmLabel:"Discard",tone:"danger"})}let[ez,eD]=(0,h.useState)(!1);async function e_(){await eM()&&(ei({...(0,q.withUrl)((0,q.defaultRequestDraft)(),"{{practiceApi}}/products"),checks:[{type:"status",expect:"2xx"},{type:"json",path:"items[0].name",op:"exists",value:""}]}),eA(null),ep(null),ey(!1),ew(null),eq("response"),e("Practice request ready — press Send","success"))}async function eV(){try{let t=await C.workspaceApi.index(),s=e=>t.requests.find(t=>"Practice"===t.collection&&t.name===e),a=s("Sign in")?.id??(await C.workspaceApi.create({name:"Sign in",collection:"Practice",request:{...(0,q.withUrl)({...(0,q.defaultRequestDraft)(),method:"POST"},"{{practiceApi}}/login"),bodyMode:"json",bodyText:'{\n "username": "you",\n "password": "demo"\n}',checks:[{type:"status",expect:"200"}]}})).id,n=s("My orders"),r=n?await C.workspaceApi.get(n.id):await C.workspaceApi.create({name:"My orders",collection:"Practice",request:{...(0,q.withUrl)((0,q.defaultRequestDraft)(),"{{practiceApi}}/orders"),authMode:"bearer",token:"{{token}}",checks:[{type:"status",expect:"200"}],before:{requestId:a,requestName:"Sign in",extract:[{name:"token",from:"json",path:"data.token"}]}}});await U(),eF(!0),await eB(r),e("Added Practice → Sign in and My orders. Press Send: it signs in first, then uses the token.","success")}catch(t){e(t instanceof Error?t.message:"Could not add the practice requests","error")}}async function eB(e){if(!await eM())return;let t=(0,q.requestFromUnknown)(e.request);ei(t),eA({id:e.id,name:e.name,collection:e.collection,snapshot:JSON.stringify(t)}),ep(null),ey(!1),ew(null),eq("response")}async function eH(){await eM()&&(ei((0,q.defaultRequestDraft)()),eA(null),ep(null),ew(null),window.setTimeout(()=>er.current?.focus(),0))}async function eJ(){try{ew(null);let e=await (0,_.withFolders)(el,P?.collection,S),t=(0,q.resolveDraft)(e.draft,e.vars,E?.name),s=(0,q.buildPayload)(t,(0,q.toLoadConfig)(eo),(0,q.autoRunName)(t,P?.name),(0,q.targetsFromSlo)(N));return await (0,D.withRunFirst)(s,t,S,E?.name)}catch(e){return ew(e instanceof Error?e.message:"Request is not valid"),null}}async function eW(){try{let e={...el,method:"POST",bodyMode:"graphql",graphqlQuery:s.INTROSPECTION_QUERY,graphqlVariables:"",graphqlOperation:"IntrospectionQuery",graphqlErrorsFail:!1,checks:[],saveValues:[],testData:null},t=await (0,_.withFolders)(e,P?.collection,S),a=(0,q.resolveDraft)(t.draft,t.vars,E?.name),{request:n,auth:r,options:l,setup:i}=await (0,D.withRunFirst)((0,q.buildPayload)(a,(0,q.toLoadConfig)(eo),"schema"),a,S,E?.name),o=await fetch("/engine/graphql/introspect",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({request:n,auth:r,options:l,setup:i})}),c=await o.json();return o.ok?c:{status:0,body:"",error:c.error??`Engine error (${o.status})`}}catch(e){return{status:0,body:"",error:e instanceof Error?e.message:String(e)}}}async function eK(){if(eT||!eL)return;let e=await eJ();if(e){ex(!0),ey(!1),eq("response");try{let t=await (0,O.sendRequest)(e);ep(t);let s=(t.saved??[]).flatMap(e=>e.found&&void 0!==e.value?[{name:e.name,value:e.value}]:[]);$(s,P?.name??"the last Send")}finally{ex(!1)}}}async function eQ(s=!1){if(eT||e$||!eL||!i.k6Ready)return;if(eP)return void ew(eP);let a=await eJ();if(a){if(ey(!1),!s){eb(!0);try{let e=await (0,O.sendRequest)(a);if(ep(e),!(0,O.isSuccess)(e)){ey(!0),eq("response");return}}finally{eb(!1)}}if((0,O.needsLoadConfirm)(eo.preset,a.load,a.request.url)&&!await n({title:`Start a ${(0,x.profileSummary)(eo)} load test against ${(0,O.hostOf)(a.request.url)}?`,body:(0,t.jsxs)(t.Fragment,{children:["This is a ",(0,t.jsx)("span",{className:"text-ink",children:eo.preset})," profile against a non-local host (",(0,x.profileSummary)(eo),"). 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 load test",tone:"danger"}))return;try{let e=await (0,O.startLoadRun)(a);Q(e.id),ek(e),eq("report")}catch(t){e(t instanceof Error?t.message:"Failed to start load","error")}}}async function eY(){if(!ej)return;let t=await (0,O.stopLoadRun)(ej.id);t?ek(t):e("Could not reach the engine to stop the run","error")}(0,h.useEffect)(()=>{let e=()=>eD(!(0,B.welcomeHidden)());return e(),window.addEventListener(B.WELCOME_EVENT,e),()=>window.removeEventListener(B.WELCOME_EVENT,e)},[]),(0,h.useEffect)(()=>{let t=()=>{let t=null;try{t=sessionStorage.getItem(H.OPEN_REQUEST_KEY),sessionStorage.removeItem(H.OPEN_REQUEST_KEY)}catch{}t&&C.workspaceApi.get(t).then(e=>void eB(e)).catch(()=>e("That saved request is gone","error"))};return ed&&t(),window.addEventListener(H.OPEN_REQUEST_EVENT,t),()=>window.removeEventListener(H.OPEN_REQUEST_EVENT,t)},[ed]),(0,z.useShortcuts)({send:()=>void eK(),run:()=>void eQ(),focusUrl:()=>er.current?.focus(),save:()=>P?void eI():es(!0)});let eG=i.k6Ready?eL?eP??void 0:"Enter a URL first":i.k6Label,eX=(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{type:"button","data-tour":"send",onClick:()=>void eK(),disabled:eT||!eL,title:`Send one request (${k}+Enter)`,className:"btn btn-primary",children:[eh?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(m.Send,{size:16}),"Send"]}),e$?(0,t.jsxs)("button",{type:"button",onClick:()=>void eY(),disabled:ej?.stopping,className:"btn btn-danger",children:[ej?.stopping?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(p.Square,{size:16}),ej?.stopping?"Stopping…":"Stop"]}):(0,t.jsxs)("button",{type:"button","data-tour":"run",onClick:()=>void eQ(),disabled:eT||!!eG,title:eG??`Check the request, then run the load profile (${k}+Shift+Enter)`,className:"btn btn-secondary",children:[ef?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(d.Play,{size:16}),ef?"Checking…":"Run load test"]})]});return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsxs)("header",{className:"border-b border-line bg-panel px-4 py-3 lg:px-6",children:[(0,t.jsx)("h1",{className:"sr-only",children:"Test an API"}),(0,t.jsx)(f.RequestBar,{ref:er,draft:el,onChange:e=>{ei(e),ew(null)},onImported:t=>e(t,"success"),actions:eX}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-mute",children:[ea?null:(0,t.jsxs)("button",{type:"button",onClick:()=>eF(!0),className:"inline-flex items-center gap-1 rounded-md px-1.5 py-1 hover:text-ink",children:[(0,t.jsx)(r.FolderOpen,{size:13,"aria-hidden":!0})," Saved requests"]}),(0,t.jsx)(j.EnvironmentBar,{drafts:[el],collections:[P?.collection]}),(0,t.jsx)(L,{draft:el,sent:!!(em&&em.status>0),onChange:ei}),et?(0,t.jsx)(T.SaveRequestForm,{initial:{name:P?.name??(0,q.autoRunName)(el).replace(/ · \d.*$/,""),collection:P?.collection??""},onSave:(e,t)=>void eI({name:e,collection:t}),onCancel:()=>es(!1)}):(0,t.jsxs)("span",{className:"inline-flex items-center gap-2",children:[P?(0,t.jsxs)("span",{className:"text-ink",title:P.collection?`${P.collection} / ${P.name}`:P.name,children:[P.collection?(0,t.jsxs)("span",{className:"text-mute",children:[P.collection," / "]}):null,P.name,eO?(0,t.jsx)("span",{className:"ml-1 text-warn","aria-label":"unsaved changes",children:"● unsaved"}):null]}):null,(0,t.jsxs)("button",{type:"button",onClick:()=>P?void eI():es(!0),disabled:!!P&&!eO,title:`Save request (${k}+S)`,className:"inline-flex items-center gap-1 rounded-md border border-line px-2 py-0.5 text-ink hover:border-accent disabled:opacity-40",children:[(0,t.jsx)(u,{size:12,"aria-hidden":!0})," ",P?"Save":"Save request"]}),P?(0,t.jsx)("button",{type:"button",onClick:()=>es(!0),className:"rounded-md px-1.5 py-0.5 hover:text-ink",children:"Save as…"}):null]}),ev?(0,t.jsx)("span",{className:"text-bad",role:"alert",children:ev}):null,(0,t.jsxs)("span",{className:"ml-auto hidden items-center gap-1.5 sm:inline-flex",children:[(0,t.jsx)("span",{className:"kbd",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," send",(0,t.jsx)("span",{className:"kbd ml-2",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Shift"}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," load",(0,t.jsx)("span",{className:"kbd ml-2",children:"/"})," URL"]})]})]}),(0,t.jsxs)("div",{className:`grid min-h-0 flex-1 overflow-y-auto lg:overflow-hidden ${eC?"":ea?"lg:grid-cols-[15rem_minmax(0,1fr)_minmax(0,1fr)] 2xl:grid-cols-[16rem_minmax(0,5fr)_minmax(0,7fr)]":"lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)] 2xl:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]"}`,children:[!eC&&ea?(0,t.jsx)(T.RequestsPanel,{activeId:P?.id??null,onOpen:e=>void eB(e),onNew:()=>void eH(),onClose:()=>eF(!1)}):null,eC?null:(0,t.jsx)("section",{"aria-label":"Request",className:"min-w-0 px-4 py-4 lg:overflow-y-auto lg:px-6",children:(0,t.jsx)(b.RequestEditor,{id:"lab-request",draft:el,onChange:ei,checkResults:em?.checks,setupResult:em?.setup,savedResults:em?.saved,currentId:P?.id,collection:P?.collection,introspect:eW,extraTabs:[{id:"load",label:"Load",badge:eo.stages?.length?"stages":"rate"===eo.mode?`${eo.rps}/s`:`${eo.vus} users \xb7 ${eo.duration}`,content:(0,t.jsx)(x.LoadEditor,{load:eo,onChange:ec})},{id:"targets",label:"Goals",content:(0,t.jsx)(ee,{})}]})}),(0,t.jsxs)("section",{"aria-label":"Results",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.jsx)(w.Tabs,{id:"lab-results",label:"Results",value:eR,onChange:eq,items:[{id:"response",label:"Response",badge:em?em.status||"ERR":void 0},{id:"report",label:e$?(0,t.jsx)(Y,{}):"Load report",badge:eE.length||void 0}],trailing:(0,t.jsxs)(t.Fragment,{children:["report"===eR&&eE.length>0?(0,t.jsx)(X,{runs:eE,current:ej,disabled:e$,onPick:async t=>{try{let e=await I.historyApi.run(t.id);Q(t.id),ek({id:e.report.id,status:e.report.status,report:e.report})}catch(t){e(t instanceof Error?t.message:"Could not open that run","error")}}}):null,(0,t.jsx)("button",{type:"button",onClick:()=>eU(e=>!e),"aria-label":eC?"Show the request editor":"Expand results to full width",title:eC?"Show the request editor":"Expand results",className:"hidden rounded p-1.5 text-mute hover:bg-panel-2 hover:text-ink lg:block",children:eC?(0,t.jsx)(c,{size:14}):(0,t.jsx)(o,{size:14})})]})}),(0,t.jsx)("div",{...(0,w.tabPanelProps)("lab-results",eR),className:"flex min-h-0 flex-1 flex-col pt-4",children:"response"===eR?(0,t.jsxs)(t.Fragment,{children:[eg&&em?(0,t.jsxs)("div",{role:"alert",className:"mb-4 flex flex-wrap items-center gap-3 rounded-md border border-warn/40 bg-warn/10 px-3 py-2.5",children:[(0,t.jsxs)("p",{className:"min-w-0 flex-1 text-sm text-ink",children:[(0,t.jsx)("span",{className:"font-medium text-warn",children:"Load test not started."})," The check returned"," ",em.status||"an error",", not 2xx. Fix the request, or run anyway if this status is expected."]}),(0,t.jsx)("button",{type:"button",className:"btn btn-secondary py-1.5 text-xs",onClick:()=>void eQ(!0),children:"Run anyway"})]}):null,em?(0,t.jsx)(y.ResponseViewer,{result:em}):ez?(0,t.jsx)(B.WelcomeCard,{practiceReady:!!i.demoApi,onSimple:()=>void e_(),onSignIn:()=>void eV(),onHide:()=>(0,B.setWelcomeHidden)(!0)}):(0,t.jsx)(G,{title:"Send a request to see the response",lines:[(0,t.jsx)(t.Fragment,{children:"Paste a URL — or a whole curl command from your browser's DevTools — into the bar above."}),(0,t.jsxs)(t.Fragment,{children:["Press ",(0,t.jsx)("span",{className:"kbd",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," to send it."]})]})]}):ej?(0,t.jsxs)(t.Fragment,{children:[ej.error?(0,t.jsx)("p",{role:"alert",className:"mb-3 rounded-md border border-bad/40 bg-bad/10 px-3 py-2 text-sm text-bad",children:ej.error}):null,(0,t.jsx)(g.ReportView,{report:ej.report,source:"session",live:e$,probe:em})]}):(0,t.jsx)(G,{title:"No load test yet",lines:[(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-ink",children:"Run load test"})," sends one check request first, then runs"," ",(0,t.jsx)("span",{className:"font-mono text-ink",children:(0,x.profileSummary)(eo)})," with k6."]}),(0,t.jsx)(t.Fragment,{children:"Change users, duration, and ramps in the Load tab. Set pass/fail goals in Goals."})],action:(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",disabled:eT||!!eG,title:eG,onClick:()=>void eQ(),children:[(0,t.jsx)(d.Play,{size:16}),"Run load test"]})})})]})]})]})},"VerdictTag",0,Z],6980)},17219,15060,e=>{"use strict";let t=new Uint32Array(256).map((e,t)=>{let s=t;for(let e=0;e<8;e++)s=1&s?0xedb88320^s>>>1:s>>>1;return s>>>0});function s(e){let t=new Uint8Array(2);return new DataView(t.buffer).setUint16(0,e,!0),t}function a(e){let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),t}function n(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),s=0;for(let a of e)t.set(a,s),s+=a.length;return t}function r(e,t){let s=URL.createObjectURL(t),a=document.createElement("a");a.href=s,a.download=e,document.body.appendChild(a),a.click(),a.remove(),URL.revokeObjectURL(s)}e.s(["zipStore",0,function(e){let r=new TextEncoder,l=[],i=[],o=0;for(let[c,d]of Object.entries(e)){let e=r.encode(c),u="string"==typeof d?r.encode(d):d,m=function(e){let s=0xffffffff;for(let a of e)s=t[(s^a)&255]^s>>>8;return(0xffffffff^s)>>>0}(u),p=n([a(0x4034b50),s(20),s(0),s(0),s(0),s(0),a(m),a(u.length),a(u.length),s(e.length),s(0),e,u]),h=n([a(0x2014b50),s(20),s(20),s(0),s(0),s(0),s(0),a(m),a(u.length),a(u.length),s(e.length),s(0),s(0),s(0),s(0),a(0),a(o),e]);l.push(p),i.push(h),o+=p.length}let c=n(i),d=n([a(0x6054b50),s(0),s(0),s(Object.keys(e).length),s(Object.keys(e).length),a(c.length),a(o),s(0)]),u=n([...l,c,d]);return new Blob([u.buffer.slice(u.byteOffset,u.byteOffset+u.byteLength)],{type:"application/zip"})}],17219),e.s(["downloadBlob",0,r,"downloadText",0,function(e,t,s){r(e,new Blob([t],{type:s}))}],15060)},3792,66478,14168,e=>{"use strict";var t=e.i(99522);let s=(0,t.default)("play",[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]]);e.s(["Play",0,s],3792);let a=(0,t.default)("square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);async function n(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error??`Engine error (${e.status})`);return t}e.s(["Square",0,a],66478);let r=(e,t,s)=>fetch(t,{method:e,headers:void 0===s?void 0:{"content-type":"application/json"},body:void 0===s?void 0:JSON.stringify(s)});e.s(["suiteApi",0,{plan:e=>fetch(`/engine/suites/plan?collection=${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>n(e)),savePlan:(e,t)=>r("PUT","/engine/suites/plan",{collection:e,...t}).then(e=>n(e)),start:e=>r("POST","/engine/suites/runs",e).then(e=>n(e)),get:e=>fetch(`/engine/suites/runs/${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>n(e)),stop:e=>r("POST",`/engine/suites/runs/${encodeURIComponent(e)}/stop`).then(e=>n(e))},"suiteHref",0,function(e){return`/suite?c=${encodeURIComponent(e)}`}],14168)}]);
|
|
2
|
+
${"completed"===s.status?n.headline:s.error??"See the report for details."}`,ok:"completed"===s.status&&"fail"!==n.overall})}},500);return()=>{t=!0,window.clearInterval(s)}},[ej?.id,e$]);let eO=!!P&&JSON.stringify(el)!==P.snapshot;function eA(e){Z(e);try{e?sessionStorage.setItem(J,JSON.stringify(e)):sessionStorage.removeItem(J)}catch{}}function eF(e){en(e);try{localStorage.setItem(W,e?"open":"closed")}catch{}}async function eI(t){try{let s={name:t?.name??P.name,collection:t?.collection??P.collection,request:el},a=P&&!t?await C.workspaceApi.update(P.id,s):await C.workspaceApi.create(s);eA({id:a.id,name:a.name,collection:a.collection,snapshot:JSON.stringify(el)}),es(!1),await U(),e(`Saved “${a.name}”${a.collection?` in ${a.collection}`:""}`,"success")}catch(t){e(t instanceof Error?t.message:"Could not save the request","error")}}async function eM(){return!eO||n({title:`Discard changes to “${P.name}”?`,body:"They have not been saved.",confirmLabel:"Discard",tone:"danger"})}let[ez,eD]=(0,h.useState)(!1);async function e_(){await eM()&&(ei({...(0,q.withUrl)((0,q.defaultRequestDraft)(),"{{practiceApi}}/products"),checks:[{type:"status",expect:"2xx"},{type:"json",path:"items[0].name",op:"exists",value:""}]}),eA(null),ep(null),ey(!1),ew(null),eq("response"),e("Practice request ready — press Send","success"))}async function eV(){try{let t=await C.workspaceApi.index(),s=e=>t.requests.find(t=>"Practice"===t.collection&&t.name===e),a=s("Sign in")?.id??(await C.workspaceApi.create({name:"Sign in",collection:"Practice",request:{...(0,q.withUrl)({...(0,q.defaultRequestDraft)(),method:"POST"},"{{practiceApi}}/login"),bodyMode:"json",bodyText:'{\n "username": "you",\n "password": "demo"\n}',checks:[{type:"status",expect:"200"}]}})).id,n=s("My orders"),r=n?await C.workspaceApi.get(n.id):await C.workspaceApi.create({name:"My orders",collection:"Practice",request:{...(0,q.withUrl)((0,q.defaultRequestDraft)(),"{{practiceApi}}/orders"),authMode:"bearer",token:"{{token}}",checks:[{type:"status",expect:"200"}],before:{requestId:a,requestName:"Sign in",extract:[{name:"token",from:"json",path:"data.token"}]}}});await U(),eF(!0),await eB(r),e("Added Practice → Sign in and My orders. Press Send: it signs in first, then uses the token.","success")}catch(t){e(t instanceof Error?t.message:"Could not add the practice requests","error")}}async function eB(e){if(!await eM())return;let t=(0,q.requestFromUnknown)(e.request);ei(t),eA({id:e.id,name:e.name,collection:e.collection,snapshot:JSON.stringify(t)}),ep(null),ey(!1),ew(null),eq("response")}async function eH(){await eM()&&(ei((0,q.defaultRequestDraft)()),eA(null),ep(null),ew(null),window.setTimeout(()=>er.current?.focus(),0))}async function eJ(){try{ew(null);let e=await (0,_.withFolders)(el,P?.collection,S),t=(0,q.resolveDraft)(e.draft,e.vars,E?.name),s=(0,q.buildPayload)(t,(0,q.toLoadConfig)(eo),(0,q.autoRunName)(t,P?.name),(0,q.targetsFromSlo)(N));return await (0,D.withRunFirst)(s,t,S,E?.name)}catch(e){return ew(e instanceof Error?e.message:"Request is not valid"),null}}async function eW(){try{let e={...el,method:"POST",bodyMode:"graphql",graphqlQuery:s.INTROSPECTION_QUERY,graphqlVariables:"",graphqlOperation:"IntrospectionQuery",graphqlErrorsFail:!1,checks:[],saveValues:[],testData:null},t=await (0,_.withFolders)(e,P?.collection,S),a=(0,q.resolveDraft)(t.draft,t.vars,E?.name),{request:n,auth:r,options:l,setup:i}=await (0,D.withRunFirst)((0,q.buildPayload)(a,(0,q.toLoadConfig)(eo),"schema"),a,S,E?.name),o=await fetch("/engine/graphql/introspect",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({request:n,auth:r,options:l,setup:i})}),c=await o.json();return o.ok?c:{status:0,body:"",error:c.error??`Engine error (${o.status})`}}catch(e){return{status:0,body:"",error:e instanceof Error?e.message:String(e)}}}async function eK(){if(eT||!eL)return;let e=await eJ();if(e){ex(!0),ey(!1),eq("response");try{let t=await (0,O.sendRequest)(e);ep(t);let s=(t.saved??[]).flatMap(e=>e.found&&void 0!==e.value?[{name:e.name,value:e.value}]:[]);$(s,P?.name??"the last Send")}finally{ex(!1)}}}async function eQ(s=!1){if(eT||e$||!eL||!i.k6Ready)return;if(eP)return void ew(eP);let a=await eJ();if(a){if(ey(!1),!s){eb(!0);try{let e=await (0,O.sendRequest)(a);if(ep(e),!(0,O.isSuccess)(e)){ey(!0),eq("response");return}}finally{eb(!1)}}if((0,O.needsLoadConfirm)(eo.preset,a.load,a.request.url)&&!await n({title:`Start a ${(0,x.profileSummary)(eo)} load test against ${(0,O.hostOf)(a.request.url)}?`,body:(0,t.jsxs)(t.Fragment,{children:["This is a ",(0,t.jsx)("span",{className:"text-ink",children:eo.preset})," profile against a non-local host (",(0,x.profileSummary)(eo),"). 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 load test",tone:"danger"}))return;try{let e=await (0,O.startLoadRun)(a);Q(e.id),ek(e),eq("report")}catch(t){e(t instanceof Error?t.message:"Failed to start load","error")}}}async function eY(){if(!ej)return;let t=await (0,O.stopLoadRun)(ej.id);t?ek(t):e("Could not reach the engine to stop the run","error")}(0,h.useEffect)(()=>{let e=()=>eD(!(0,B.welcomeHidden)());return e(),window.addEventListener(B.WELCOME_EVENT,e),()=>window.removeEventListener(B.WELCOME_EVENT,e)},[]),(0,h.useEffect)(()=>{let t=()=>{let t=null;try{t=sessionStorage.getItem(H.OPEN_REQUEST_KEY),sessionStorage.removeItem(H.OPEN_REQUEST_KEY)}catch{}t&&C.workspaceApi.get(t).then(e=>void eB(e)).catch(()=>e("That saved request is gone","error"))};return ed&&t(),window.addEventListener(H.OPEN_REQUEST_EVENT,t),()=>window.removeEventListener(H.OPEN_REQUEST_EVENT,t)},[ed]),(0,z.useShortcuts)({send:()=>void eK(),run:()=>void eQ(),focusUrl:()=>er.current?.focus(),save:()=>P?void eI():es(!0)});let eG=i.k6Ready?eL?eP??void 0:"Enter a URL first":i.k6Label,eX=(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{type:"button","data-tour":"send",onClick:()=>void eK(),disabled:eT||!eL,title:`Send one request (${k}+Enter)`,className:"btn btn-primary",children:[eh?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(m.Send,{size:16}),"Send"]}),e$?(0,t.jsxs)("button",{type:"button",onClick:()=>void eY(),disabled:ej?.stopping,className:"btn btn-danger",children:[ej?.stopping?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(p.Square,{size:16}),ej?.stopping?"Stopping…":"Stop"]}):(0,t.jsxs)("button",{type:"button","data-tour":"run",onClick:()=>void eQ(),disabled:eT||!!eG,title:eG??`Check the request, then run the load profile (${k}+Shift+Enter)`,className:"btn btn-secondary",children:[ef?(0,t.jsx)(l.Loader2,{size:16,className:"animate-spin"}):(0,t.jsx)(d.Play,{size:16}),ef?"Checking…":"Run load test"]})]});return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col",children:[(0,t.jsxs)("header",{className:"border-b border-line bg-panel px-4 py-3 lg:px-6",children:[(0,t.jsx)("h1",{className:"sr-only",children:"Test an API"}),(0,t.jsx)(f.RequestBar,{ref:er,draft:el,onChange:e=>{ei(e),ew(null)},onImported:t=>e(t,"success"),actions:eX}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-mute",children:[ea?null:(0,t.jsxs)("button",{type:"button",onClick:()=>eF(!0),className:"inline-flex items-center gap-1 rounded-md px-1.5 py-1 hover:text-ink",children:[(0,t.jsx)(r.FolderOpen,{size:13,"aria-hidden":!0})," Saved requests"]}),(0,t.jsx)(j.EnvironmentBar,{drafts:[el],collections:[P?.collection]}),(0,t.jsx)(L,{draft:el,sent:!!(em&&em.status>0),onChange:ei}),et?(0,t.jsx)(T.SaveRequestForm,{initial:{name:P?.name??(0,q.autoRunName)(el).replace(/ · \d.*$/,""),collection:P?.collection??""},onSave:(e,t)=>void eI({name:e,collection:t}),onCancel:()=>es(!1)}):(0,t.jsxs)("span",{className:"inline-flex items-center gap-2",children:[P?(0,t.jsxs)("span",{className:"text-ink",title:P.collection?`${P.collection} / ${P.name}`:P.name,children:[P.collection?(0,t.jsxs)("span",{className:"text-mute",children:[P.collection," / "]}):null,P.name,eO?(0,t.jsx)("span",{className:"ml-1 text-warn","aria-label":"unsaved changes",children:"● unsaved"}):null]}):null,(0,t.jsxs)("button",{type:"button",onClick:()=>P?void eI():es(!0),disabled:!!P&&!eO,title:`Save request (${k}+S)`,className:"inline-flex items-center gap-1 rounded-md border border-line px-2 py-0.5 text-ink hover:border-accent disabled:opacity-40",children:[(0,t.jsx)(u,{size:12,"aria-hidden":!0})," ",P?"Save":"Save request"]}),P?(0,t.jsx)("button",{type:"button",onClick:()=>es(!0),className:"rounded-md px-1.5 py-0.5 hover:text-ink",children:"Save as…"}):null]}),ev?(0,t.jsx)("span",{className:"text-bad",role:"alert",children:ev}):null,(0,t.jsxs)("span",{className:"ml-auto hidden items-center gap-1.5 sm:inline-flex",children:[(0,t.jsx)("span",{className:"kbd",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," send",(0,t.jsx)("span",{className:"kbd ml-2",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Shift"}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," load",(0,t.jsx)("span",{className:"kbd ml-2",children:"/"})," URL"]})]})]}),(0,t.jsxs)("div",{className:`grid min-h-0 flex-1 overflow-y-auto lg:overflow-hidden ${eC?"":ea?"lg:grid-cols-[15rem_minmax(0,1fr)_minmax(0,1fr)] 2xl:grid-cols-[16rem_minmax(0,5fr)_minmax(0,7fr)]":"lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)] 2xl:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]"}`,children:[!eC&&ea?(0,t.jsx)(T.RequestsPanel,{activeId:P?.id??null,onOpen:e=>void eB(e),onNew:()=>void eH(),onClose:()=>eF(!1)}):null,eC?null:(0,t.jsx)("section",{"aria-label":"Request",className:"min-w-0 px-4 py-4 lg:overflow-y-auto lg:px-6",children:(0,t.jsx)(b.RequestEditor,{id:"lab-request",draft:el,onChange:ei,checkResults:em?.checks,lastBody:em?.body,setupResult:em?.setup,savedResults:em?.saved,currentId:P?.id,collection:P?.collection,introspect:eW,extraTabs:[{id:"load",label:"Load",badge:eo.stages?.length?"stages":"rate"===eo.mode?`${eo.rps}/s`:`${eo.vus} users \xb7 ${eo.duration}`,content:(0,t.jsx)(x.LoadEditor,{load:eo,onChange:ec})},{id:"targets",label:"Goals",content:(0,t.jsx)(ee,{})}]})}),(0,t.jsxs)("section",{"aria-label":"Results",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.jsx)(w.Tabs,{id:"lab-results",label:"Results",value:eR,onChange:eq,items:[{id:"response",label:"Response",badge:em?em.status||"ERR":void 0},{id:"report",label:e$?(0,t.jsx)(Y,{}):"Load report",badge:eE.length||void 0}],trailing:(0,t.jsxs)(t.Fragment,{children:["report"===eR&&eE.length>0?(0,t.jsx)(X,{runs:eE,current:ej,disabled:e$,onPick:async t=>{try{let e=await I.historyApi.run(t.id);Q(t.id),ek({id:e.report.id,status:e.report.status,report:e.report})}catch(t){e(t instanceof Error?t.message:"Could not open that run","error")}}}):null,(0,t.jsx)("button",{type:"button",onClick:()=>eU(e=>!e),"aria-label":eC?"Show the request editor":"Expand results to full width",title:eC?"Show the request editor":"Expand results",className:"hidden rounded p-1.5 text-mute hover:bg-panel-2 hover:text-ink lg:block",children:eC?(0,t.jsx)(c,{size:14}):(0,t.jsx)(o,{size:14})})]})}),(0,t.jsx)("div",{...(0,w.tabPanelProps)("lab-results",eR),className:"flex min-h-0 flex-1 flex-col pt-4",children:"response"===eR?(0,t.jsxs)(t.Fragment,{children:[eg&&em?(0,t.jsxs)("div",{role:"alert",className:"mb-4 flex flex-wrap items-center gap-3 rounded-md border border-warn/40 bg-warn/10 px-3 py-2.5",children:[(0,t.jsxs)("p",{className:"min-w-0 flex-1 text-sm text-ink",children:[(0,t.jsx)("span",{className:"font-medium text-warn",children:"Load test not started."})," The check returned"," ",em.status||"an error",", not 2xx. Fix the request, or run anyway if this status is expected."]}),(0,t.jsx)("button",{type:"button",className:"btn btn-secondary py-1.5 text-xs",onClick:()=>void eQ(!0),children:"Run anyway"})]}):null,em?(0,t.jsx)(y.ResponseViewer,{result:em}):ez?(0,t.jsx)(B.WelcomeCard,{practiceReady:!!i.demoApi,onSimple:()=>void e_(),onSignIn:()=>void eV(),onHide:()=>(0,B.setWelcomeHidden)(!0)}):(0,t.jsx)(G,{title:"Send a request to see the response",lines:[(0,t.jsx)(t.Fragment,{children:"Paste a URL — or a whole curl command from your browser's DevTools — into the bar above."}),(0,t.jsxs)(t.Fragment,{children:["Press ",(0,t.jsx)("span",{className:"kbd",children:k}),"+",(0,t.jsx)("span",{className:"kbd",children:"Enter"})," to send it."]})]})]}):ej?(0,t.jsxs)(t.Fragment,{children:[ej.error?(0,t.jsx)("p",{role:"alert",className:"mb-3 rounded-md border border-bad/40 bg-bad/10 px-3 py-2 text-sm text-bad",children:ej.error}):null,(0,t.jsx)(g.ReportView,{report:ej.report,source:"session",live:e$,probe:em})]}):(0,t.jsx)(G,{title:"No load test yet",lines:[(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-ink",children:"Run load test"})," sends one check request first, then runs"," ",(0,t.jsx)("span",{className:"font-mono text-ink",children:(0,x.profileSummary)(eo)})," with k6."]}),(0,t.jsx)(t.Fragment,{children:"Change users, duration, and ramps in the Load tab. Set pass/fail goals in Goals."})],action:(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",disabled:eT||!!eG,title:eG,onClick:()=>void eQ(),children:[(0,t.jsx)(d.Play,{size:16}),"Run load test"]})})})]})]})]})},"VerdictTag",0,Z],6980)},17219,15060,e=>{"use strict";let t=new Uint32Array(256).map((e,t)=>{let s=t;for(let e=0;e<8;e++)s=1&s?0xedb88320^s>>>1:s>>>1;return s>>>0});function s(e){let t=new Uint8Array(2);return new DataView(t.buffer).setUint16(0,e,!0),t}function a(e){let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),t}function n(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),s=0;for(let a of e)t.set(a,s),s+=a.length;return t}function r(e,t){let s=URL.createObjectURL(t),a=document.createElement("a");a.href=s,a.download=e,document.body.appendChild(a),a.click(),a.remove(),URL.revokeObjectURL(s)}e.s(["zipStore",0,function(e){let r=new TextEncoder,l=[],i=[],o=0;for(let[c,d]of Object.entries(e)){let e=r.encode(c),u="string"==typeof d?r.encode(d):d,m=function(e){let s=0xffffffff;for(let a of e)s=t[(s^a)&255]^s>>>8;return(0xffffffff^s)>>>0}(u),p=n([a(0x4034b50),s(20),s(0),s(0),s(0),s(0),a(m),a(u.length),a(u.length),s(e.length),s(0),e,u]),h=n([a(0x2014b50),s(20),s(20),s(0),s(0),s(0),s(0),a(m),a(u.length),a(u.length),s(e.length),s(0),s(0),s(0),s(0),a(0),a(o),e]);l.push(p),i.push(h),o+=p.length}let c=n(i),d=n([a(0x6054b50),s(0),s(0),s(Object.keys(e).length),s(Object.keys(e).length),a(c.length),a(o),s(0)]),u=n([...l,c,d]);return new Blob([u.buffer.slice(u.byteOffset,u.byteOffset+u.byteLength)],{type:"application/zip"})}],17219),e.s(["downloadBlob",0,r,"downloadText",0,function(e,t,s){r(e,new Blob([t],{type:s}))}],15060)},3792,66478,14168,e=>{"use strict";var t=e.i(99522);let s=(0,t.default)("play",[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]]);e.s(["Play",0,s],3792);let a=(0,t.default)("square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);async function n(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error??`Engine error (${e.status})`);return t}e.s(["Square",0,a],66478);let r=(e,t,s)=>fetch(t,{method:e,headers:void 0===s?void 0:{"content-type":"application/json"},body:void 0===s?void 0:JSON.stringify(s)});e.s(["suiteApi",0,{plan:e=>fetch(`/engine/suites/plan?collection=${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>n(e)),savePlan:(e,t)=>r("PUT","/engine/suites/plan",{collection:e,...t}).then(e=>n(e)),start:e=>r("POST","/engine/suites/runs",e).then(e=>n(e)),get:e=>fetch(`/engine/suites/runs/${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>n(e)),stop:e=>r("POST",`/engine/suites/runs/${encodeURIComponent(e)}/stop`).then(e=>n(e))},"suiteHref",0,function(e){return`/suite?c=${encodeURIComponent(e)}`}],14168)}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,63343,44794,36620,73436,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(m(e.target.value,a,n)),className:"input font-mono"})]})}function h({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:m(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 m(e,t,s){let a=Math.round(Number(e));return Number.isFinite(a)?Math.min(s,Math.max(t,a)):t}function p(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 x(e){let{totalMs:t,peak:s}=p(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}=p(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:x(e)})]}),(0,t.jsxs)("svg",{viewBox:"0 0 300 56",preserveAspectRatio:"none",className:"h-14 w-full",role:"img","aria-label":`Load profile: ${x(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,m]=(0,r.useState)(!1),p=t=>a({...e,...t,preset:"custom"}),x="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=>p({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 p({stages:null});let a=x?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}),p({stages:n})},options:[{value:"simple",label:"Ramp · hold · down"},{value:"stages",label:"Step by step"}]})]})]}),f?(0,t.jsx)(h,{stages:e.stages,unit:x?"req/s":"VUs",rate:x,onChange:e=>p({stages:e})}):(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[x?(0,t.jsx)(u,{label:"Requests / second",value:e.rps??20,min:1,max:1e5,onChange:e=>p({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=>p({vus:e})}),(0,t.jsx)(i.LabeledInput,{label:"Hold for",mono:!0,value:e.duration,error:(0,d.durationError)(e.duration,!1),onChange:e=>p({duration:e})}),(0,t.jsx)(i.LabeledInput,{label:"Ramp up",mono:!0,value:e.rampUp,error:(0,d.durationError)(e.rampUp),onChange:e=>p({rampUp:e})}),(0,t.jsx)(i.LabeledInput,{label:"Ramp down",mono:!0,value:e.rampDown,error:(0,d.durationError)(e.rampDown),onChange:e=>p({rampDown:e})})]}),x?(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=>p({maxVus:e})})}):null,(0,t.jsx)(b,{load:e}),(0,t.jsx)("button",{type:"button",className:"text-xs text-accent hover:underline",onClick:()=>m(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:[x?(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=>p({thinkTimeMs:e})}),(0,t.jsx)(u,{label:"Random extra (ms)",value:e.thinkJitterMs,min:0,max:6e5,onChange:e=>p({thinkJitterMs:e})})]}),(0,t.jsx)(i.LabeledInput,{label:"Graceful stop",mono:!0,value:e.gracefulStop,error:(0,d.durationError)(e.gracefulStop),onChange:e=>p({gracefulStop:e}),hint:"Time in-flight requests get to finish."})]}):null]})},"profileSummary",0,x],63343);var v=e.i(1675),g=e.i(458),j=e.i(80707);let y=null,w=null,N=new Set;function k(){return w??=fetch("/engine/local-servers",{cache:"no-store"}).then(e=>e.ok?e.json():null).then(e=>(e&&(y=e.servers),y)).catch(()=>y).finally(()=>{w=null,N.forEach(e=>e())}),N.forEach(e=>e()),w}var C=e.i(6278);let $=/^\{\{\s*([A-Za-z_][\w.-]*)\s*\}\}/,S=/^(https?):\/\/(localhost|127\.0\.0\.1)(?::(\d{1,5}))?(?=[/?#]|$)/i,q="\0none",E="\0local-other",R="apitestcenter-local-ports",T={GET:"text-ok",POST:"text-warn",PUT:"text-accent",PATCH:"text-accent",DELETE:"text-bad",HEAD:"text-mute",OPTIONS:"text-mute"};function M(){try{let e=JSON.parse(localStorage.getItem(R)??"[]");return(Array.isArray(e)?e.filter(e=>Number.isInteger(e)&&e>0&&e<65536):[]).slice(0,5)}catch{return[]}}function L(e){try{localStorage.setItem(R,JSON.stringify([e,...M().filter(t=>t!==e)].slice(0,5)))}catch{}}let P=(0,r.forwardRef)(function({draft:e,onChange:s,onImported:a,actions:l},i){let{vars:o,environments:c,activeEnv:u}=(0,C.useWorkspace)(),[h,m]=(0,r.useState)([]),[p,x]=(0,r.useState)(null),[f,b]=(0,r.useState)(!1),R=(0,r.useRef)(null);(0,r.useEffect)(()=>m(M()),[]),(0,r.useEffect)(()=>{p&&R.current?.focus()},[p]);let P=e.url,A=$.exec(P)?.[1],D=Object.entries(o).filter(([e,t])=>/^https?:\/\//i.test(t.trim())&&("practiceApi"!==e||A===e)),z=(()=>{if(f)return null;let e=$.exec(P);if(e&&D.some(([t])=>t===e[1]))return{prefix:e[0],text:`{{${e[1]}}}`,value:e[1]};let t=S.exec(P);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})(),H=P.startsWith("/"),O=H||""===P||null!=z,U=function(e){let[,t]=(0,r.useState)(0);(0,r.useEffect)(()=>{let e=()=>t(e=>e+1);return N.add(e),()=>void N.delete(e)},[]),(0,r.useEffect)(()=>{e&&null==y&&!w&&k()},[e]);let s=(0,r.useCallback)(()=>void k(),[]);return{servers:y??[],checked:null!=y,checking:null!=w,refresh:s}}(O),F=z?P.slice(z.prefix.length):P,I=e=>{let t=""===F||F.startsWith("/")||F.startsWith("?")?F:`/${F}`;return`${e}${t||(e.startsWith("{{")?"":"/")}`},B=U.servers,W=[...B.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})),...h.filter(e=>!B.some(t=>t.port===e)).map(e=>({value:`local:http:${e}`,label:`localhost:${e}`,hint:U.checked?"used before · not running now":"used before",text:`localhost ${e}`,className:"font-mono text-mute",group:"local",inline:!0}))];z?.value.startsWith("local:")&&!W.some(e=>e.value===z.value)&&W.unshift({value:z.value,label:z.text,hint:"in this request",text:z.text,className:"font-mono",group:"local",inline:!0});let V=null!=z&&!z.value.startsWith("local:"),_=[...D.length?[{id:"env",label:u?.name??"Variables",text:u?.name??"variables",defaultOpen:V||null==z,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:U.checking&&!U.checked?"checking…":`${B.length||"none"} running${U.checking?" · checking…":""}`,defaultOpen:!D.length&&null==z,action:{label:(0,t.jsx)(g.RefreshCw,{size:12,"aria-hidden":!0,className:U.checking?"animate-spin":""}),title:"Check again for running servers",onClick:U.refresh,keepOpen:!0}}],J=z?"text-accent":H?"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)(j.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 ${T[e]}`})),minWidth:140,className:`shrink-0 border-r border-line px-3 font-mono text-sm font-medium outline-none focus-visible:bg-panel ${T[e.method]}`}),p?(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(!p)return;let t=Number(p.port);!Number.isInteger(t)||t<1||t>65535||(L(t),m(M()),s((0,d.withUrl)(e,I(`${p.scheme}://localhost:${t}`))),x(null))})()},onKeyDown:e=>"Escape"===e.key&&x(null),children:[(0,t.jsx)("button",{type:"button",title:"Switch between http and https",onClick:()=>x({...p,scheme:"http"===p.scheme?"https":"http"}),className:"rounded px-1 text-accent hover:bg-panel",children:p.scheme}),(0,t.jsx)("span",{className:"text-mute",children:"://localhost:"}),(0,t.jsx)("input",{ref:R,value:p.port,onChange:e=>x({...p,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:()=>x(null),className:"rounded p-0.5 text-mute hover:text-ink",children:(0,t.jsx)(n.X,{size:14})})]}):O?(0,t.jsx)(j.Select,{label:"Base URL",value:z?.value??q,onChange:t=>{if(t===E)return x({scheme:"http",port:""});if(t===q)return s((0,d.withUrl)(e,F));if(t.startsWith("local:")){let[,a,n]=t.split(":"),r=Number(n);return L(r),m(M()),s((0,d.withUrl)(e,I(`${a}://localhost:${r}`)))}s((0,d.withUrl)(e,I(`{{${t}}}`)))},onOpen:U.refresh,minWidth:320,buttonContent:z?.text??"Base URL",groups:_,options:[...D.map(([e,t])=>({value:e,label:`{{${e}}}`,hint:t,text:e,className:"font-mono text-accent",group:"env"})),...W,{value:E,label:"Another port…",text:"another port",group:"local"},{value:q,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 ${J}`}):null,(0,t.jsx)("label",{className:"sr-only",htmlFor:"request-url",children:"Request URL"}),(0,t.jsx)("input",{ref:i,id:"request-url",value:F,spellCheck:!1,autoComplete:"off",onChange:t=>{let a=t.target.value,n=/^(https?:\/\/|\{\{)/i.test(a.trim())||""===F&&""!==a&&!/^[/?#]/.test(a);/^https?:\/\//i.test(a.trim())&&b(!0),s((0,d.withUrl)(e,z&&!n?`${z.prefix}${a}`:a))},onBlur:()=>b(!1),onPaste:t=>{let n=(0,d.withPaste)(e,t.clipboardData.getData("text"));n&&(t.preventDefault(),s(n.draft),n.note&&a?.(n.note))},placeholder:z?"/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,P],44794);var A=e.i(95486),D=e.i(99522);let z=(0,D.default)("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]);var H=e.i(89932),O=e.i(75117),U=e.i(88293);let F=(0,D.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),B=e.i(56396),W=e.i(15060);let V="<hidden>";function _(e){let t=new Set(e.secretHeaders.map(e=>e.toLowerCase())),s=e.headers.map(([e,s])=>[e,t.has(e.toLowerCase())?function(e,t){if("authorization"===e.toLowerCase()||"proxy-authorization"===e.toLowerCase()){let e=/^(\w+)\s+/.exec(t);if(e)return`${e[1]} ${V}`}return V}(e,s):s]),a=e.url;if(e.secretQuery.length)try{let t=new URL(e.url);for(let s of e.secretQuery)t.searchParams.has(s)&&t.searchParams.set(s,V);a=t.toString().replace(/%3Chidden%3E/g,V)}catch{}return{...e,url:a,headers:s}}let J=[{id:"curl",label:"curl"},{id:"powershell",label:"PowerShell"},{id:"javascript",label:"JavaScript"},{id:"python",label:"Python"},{id:"csharp",label:"C#"},{id:"java",label:"Java"},{id:"go",label:"Go"},{id:"k6",label:"k6 load test"}],K=new Set(["host","content-length","connection","accept-encoding"]),G=e=>JSON.stringify(e),X=e=>`'${e.replace(/'/g,"'\\''")}'`,Z=e=>`'${e.replace(/'/g,"''")}'`,Q=e=>`@"${e.replace(/"/g,'""')}"`,Y=(0,D.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"}]]);e.s(["Eye",0,Y],36620);let ee=(0,D.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"}]]);e.s(["EyeOff",0,ee],73436);var et=e.i(42967);let es="apitestcenter-code-target";function ea({sent:e}){let s=(0,B.useToast)(),[a,n]=(0,r.useState)(!1),[l,i]=(0,r.useState)("curl");(0,r.useEffect)(()=>i(function(){try{let e=localStorage.getItem(es);if(J.some(t=>t.id===e))return e}catch{}return"curl"}()),[]);let o=(0,r.useMemo)(()=>a?e:_(e),[e,a]),d=(0,r.useMemo)(()=>(function(e,t){let s=t.headers.filter(([e,t])=>!K.has(e.toLowerCase())&&!("user-agent"===e.toLowerCase()&&t.startsWith("ApiTestCenter/"))),a=t.body,n=t.method.toUpperCase(),r=[];switch(e){case"curl":for(let[e,l]of(r.push(`curl${"GET"===n&&void 0===a?"":` -X ${n}`} ${X(t.url)}`),s))r.push(` -H ${X(`${e}: ${l}`)}`);return void 0!==a&&r.push(` --data-raw ${X(a)}`),t.insecure&&r.push(" -k"),r.join(" \\\n");case"powershell":{let e=s.find(([e])=>"content-type"===e.toLowerCase())?.[1],l=s.filter(([e])=>"content-type"!==e.toLowerCase());if(l.length){for(let[e,t]of(r.push("$headers = @{"),l))r.push(` ${Z(e)} = ${Z(t)}`);r.push("}")}let i=[`-Uri ${Z(t.url)}`,`-Method ${n}`];return l.length&&i.push("-Headers $headers"),e&&i.push(`-ContentType ${Z(e)}`),void 0!==a&&i.push(/^[\x20-\x7e\r\n\t]*$/.test(a)?`-Body ${Z(a)}`:`-Body ([System.Text.Encoding]::UTF8.GetBytes(${Z(a)}))`),t.insecure&&i.push("-SkipCertificateCheck"),r.push(`$response = Invoke-WebRequest ${i.join(" ")}`,"$response.StatusCode","$response.Content"),r.join("\n")}case"javascript":if(r.push(`const response = await fetch(${G(t.url)}, {`,` method: ${G(n)},`),s.length){for(let[e,t]of(r.push(" headers: {"),s))r.push(` ${G(e)}: ${G(t)},`);r.push(" },")}return void 0!==a&&r.push(` body: ${G(a)},`),r.push("});","console.log(response.status);","console.log(await response.text());"),t.insecure&&r.unshift("// The certificate check was skipped in the app; in Node.js run with NODE_TLS_REJECT_UNAUTHORIZED=0 for a test server only."),r.join("\n");case"python":{if(r.push("import requests","",`url = ${G(t.url)}`),s.length){for(let[e,t]of(r.push("headers = {"),s))r.push(` ${G(e)}: ${G(t)},`);r.push("}")}void 0!==a&&r.push(`payload = ${G(a)}`);let e=[G(n),"url"];return s.length&&e.push("headers=headers"),void 0!==a&&e.push('data=payload.encode("utf-8")'),t.insecure&&e.push("verify=False"),r.push("",`response = requests.request(${e.join(", ")})`,"print(response.status_code)","print(response.text)"),r.join("\n")}case"csharp":{let e=s.find(([e])=>"content-type"===e.toLowerCase())?.[1],l=s.filter(([e])=>"content-type"!==e.toLowerCase());for(let[e,s]of(r.push("using System.Net.Http.Headers;",""),r.push(t.insecure?"using var client = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator });":"using var client = new HttpClient();"),r.push(`var request = new HttpRequestMessage(new HttpMethod(${Q(n)}), ${Q(t.url)});`),l))r.push(`request.Headers.TryAddWithoutValidation(${Q(e)}, ${Q(s)});`);return void 0!==a&&(r.push(`request.Content = new StringContent(${Q(a)});`),e&&r.push(`request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(${Q(e)});`)),r.push("var response = await client.SendAsync(request);","Console.WriteLine((int)response.StatusCode);","Console.WriteLine(await response.Content.ReadAsStringAsync());"),r.join("\n")}case"java":for(let[e,a]of(r.push("import java.net.URI;","import java.net.http.HttpClient;","import java.net.http.HttpRequest;","import java.net.http.HttpResponse;",""),t.insecure&&r.push("// The certificate check was skipped in the app; Java's HttpClient needs an SSLContext that trusts the test server."),r.push("HttpClient client = HttpClient.newHttpClient();","HttpRequest request = HttpRequest.newBuilder()",` .uri(URI.create(${G(t.url)}))`),s))r.push(` .header(${G(e)}, ${G(a)})`);return r.push(` .method(${G(n)}, ${void 0!==a?`HttpRequest.BodyPublishers.ofString(${G(a)})`:"HttpRequest.BodyPublishers.noBody()"})`," .build();"),r.push("HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());","System.out.println(response.statusCode());","System.out.println(response.body());"),r.join("\n");case"go":{let e=['"fmt"','"io"','"net/http"',...void 0!==a?['"strings"']:[],...t.insecure?['"crypto/tls"']:[]].sort();for(let[l,i]of(r.push("package main","","import (",...e.map(e=>` ${e}`),")","","func main() {"),r.push(` req, err := http.NewRequest(${G(n)}, ${G(t.url)}, ${void 0!==a?`strings.NewReader(${G(a)})`:"nil"})`),r.push(" if err != nil {"," panic(err)"," }"),s))r.push(` req.Header.Set(${G(l)}, ${G(i)})`);return r.push(t.insecure?" client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}":" client := http.DefaultClient"," res, err := client.Do(req)"," if err != nil {"," panic(err)"," }"," defer res.Body.Close()"," data, _ := io.ReadAll(res.Body)"," fmt.Println(res.StatusCode)"," fmt.Println(string(data))","}"),r.join("\n")}case"k6":if(r.push('import http from "k6/http";','import { check, sleep } from "k6";',""),r.push(`export const options = { vus: 5, duration: "30s"${t.insecure?", insecureSkipTLSVerify: true":""} };`,""),r.push("export default function () {"),r.push(` const res = http.request(${G(n)}, ${G(t.url)}, ${void 0!==a?G(a):"null"}, {`),s.length){for(let[e,t]of(r.push(" headers: {"),s))r.push(` ${G(e)}: ${G(t)},`);r.push(" },")}return r.push(" });",' check(res, { "status is 2xx": (r) => r.status >= 200 && r.status < 300 });'," sleep(1);","}"),r.join("\n")}})(l,o),[l,o]),c=(0,r.useMemo)(()=>JSON.stringify(_(e))!==JSON.stringify(e),[e]),u=(e,t)=>{navigator.clipboard.writeText(e),s(`${t} copied`,"success")};return(0,t.jsxs)("div",{className:"space-y-4 overflow-auto",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("p",{className:"min-w-0 flex-1 font-mono text-[13px] break-all text-ink",children:[(0,t.jsx)("span",{className:"mr-2 font-medium text-accent",children:o.method}),o.url]}),c?(0,t.jsxs)("button",{type:"button",onClick:()=>n(e=>!e),"aria-pressed":a,className:"inline-flex shrink-0 items-center gap-1 rounded-md border border-line px-2 py-1 text-xs text-mute hover:text-ink",children:[a?(0,t.jsx)(ee,{size:12,"aria-hidden":!0}):(0,t.jsx)(Y,{size:12,"aria-hidden":!0}),a?"Hide secrets":"Show secrets"]}):null]}),e.authNote||e.redirects?.length?(0,t.jsxs)("div",{className:"space-y-1 text-xs text-mute",children:[e.authNote?(0,t.jsxs)("p",{className:"flex items-start gap-1.5",children:[(0,t.jsx)(et.Info,{size:12,className:"mt-0.5 shrink-0","aria-hidden":!0}),e.authNote,"."]}):null,e.redirects?.length?(0,t.jsxs)("div",{children:["Then followed ",1===e.redirects.length?"a redirect":`${e.redirects.length} redirects`,":",(0,t.jsx)("ul",{className:"mt-0.5 space-y-0.5 font-mono",children:e.redirects.map((e,s)=>(0,t.jsxs)("li",{className:"break-all",children:["→ ",e]},s))})]}):null]}):null,(0,t.jsxs)("section",{"aria-label":"Headers sent",children:[(0,t.jsxs)("div",{className:"mb-1.5 flex items-center justify-between",children:[(0,t.jsx)("h3",{className:"text-xs font-medium text-mute",children:"Headers"}),(0,t.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 text-xs text-mute hover:text-ink",onClick:()=>u(o.headers.map(([e,t])=>`${e}: ${t}`).join("\n"),"Headers"),children:[(0,t.jsx)(H.Copy,{size:12})," Copy"]})]}),(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:o.headers.map(([e,s],a)=>(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 ${s.includes(V)?"text-mute italic":"text-ink"}`,children:s})]},a))})})})]}),(0,t.jsxs)("section",{"aria-label":"Body sent",children:[(0,t.jsx)("h3",{className:"mb-1.5 text-xs font-medium text-mute",children:"Body"}),void 0===e.body?(0,t.jsx)("p",{className:"text-xs text-mute",children:"No body."}):(0,t.jsxs)("pre",{className:"max-h-64 overflow-auto rounded-md border border-line bg-panel-2 p-3 font-mono text-[13px] leading-5 break-words whitespace-pre-wrap text-ink",children:[o.body,e.bodyTruncated?(0,t.jsxs)("span",{className:"text-warn",children:["\n","… first 64 KB shown"]}):null]})]}),(0,t.jsxs)("section",{"aria-label":"Code",children:[(0,t.jsxs)("div",{className:"mb-1.5 flex flex-wrap items-center gap-2",children:[(0,t.jsx)("h3",{className:"text-xs font-medium text-mute",children:"Code"}),(0,t.jsx)(j.Select,{label:"Language",value:l,onChange:e=>{i(e);try{localStorage.setItem(es,e)}catch{}},options:J.map(e=>({value:e.id,label:e.label})),minWidth:180,className:"rounded-md border border-line bg-panel-2 px-2 py-1 text-xs text-ink outline-none focus-visible:border-accent"}),(0,t.jsxs)("button",{type:"button",className:"ml-auto inline-flex items-center gap-1 text-xs text-mute hover:text-ink",onClick:()=>u(d,"Code"),children:[(0,t.jsx)(H.Copy,{size:12})," Copy"]})]}),(0,t.jsx)("pre",{"aria-label":`${J.find(e=>e.id===l)?.label} code`,className:"max-h-96 overflow-auto rounded-md border border-line bg-panel-2 p-3 font-mono text-[12.5px] leading-5 whitespace-pre text-ink",children:d}),(0,t.jsxs)("p",{className:"mt-1.5 text-xs text-mute",children:[a||!c?"":`Secrets show as ${V} — choose Show secrets to put the real values in. `,"curl"===l&&e.body&&/[^\x00-\x7f]/.test(e.body)?"On Windows, curl.exe can garble non-English letters in the command line — use the PowerShell code there, or save the body to a file and send it with --data-binary @file. ":"",e.authNote&&/signed|challenge|three requests/.test(e.authNote)?"A signature or challenge answer is only good for this one request; sent again later, the server may refuse it.":e.authNote?.startsWith("OAuth 2.0")?"The token expires; the code works until it does.":""]})]})]})}function en({cookies:e}){let[s,a]=(0,r.useState)(!1);return(0,t.jsxs)("div",{className:"space-y-2 overflow-auto",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Set by this answer",e.length>1?" and the redirects on the way":"",". With the cookie jar on, they go with the next requests to the same site."]}),(0,t.jsxs)("button",{type:"button",onClick:()=>a(e=>!e),"aria-pressed":s,className:"inline-flex shrink-0 items-center gap-1 rounded-md border border-line px-2 py-1 text-xs text-mute hover:text-ink",children:[s?(0,t.jsx)(ee,{size:12,"aria-hidden":!0}):(0,t.jsx)(Y,{size:12,"aria-hidden":!0}),s?"Hide values":"Show values"]})]}),(0,t.jsx)("div",{className:"overflow-auto rounded-md border border-line",children:(0,t.jsxs)("table",{className:"w-full text-left text-[13px]",children:[(0,t.jsx)("thead",{className:"bg-panel-2 text-xs text-mute",children:(0,t.jsxs)("tr",{children:[(0,t.jsx)("th",{className:"px-3 py-1.5 font-normal",children:"Name"}),(0,t.jsx)("th",{className:"px-3 py-1.5 font-normal",children:"Value"}),(0,t.jsx)("th",{className:"px-3 py-1.5 font-normal",children:"Domain · path"}),(0,t.jsx)("th",{className:"px-3 py-1.5 font-normal",children:"Expires"}),(0,t.jsx)("th",{className:"px-3 py-1.5 font-normal",children:"Flags"})]})}),(0,t.jsx)("tbody",{children:e.map((e,a)=>{var n;return(0,t.jsxs)("tr",{className:"border-t border-line align-top",children:[(0,t.jsx)("td",{className:"px-3 py-1.5 font-mono text-ink",children:e.name}),(0,t.jsx)("td",{className:`max-w-[16rem] px-3 py-1.5 font-mono break-all ${s?"text-ink":"text-mute italic"}`,children:s?e.value||"(empty)":V}),(0,t.jsxs)("td",{className:"px-3 py-1.5 font-mono text-xs text-mute",children:[e.domain??"this host"," · ",e.path??"/"]}),(0,t.jsx)("td",{className:"px-3 py-1.5 text-xs text-mute",children:void 0!==e.maxAge?e.maxAge<=0?"deleted":`in ${(n=e.maxAge)<120?`${n} s`:n<7200?`${Math.round(n/60)} min`:n<172800?`${Math.round(n/3600)} h`:`${Math.round(n/86400)} days`}`:e.expires?new Date(e.expires).toLocaleString():"when the app closes"}),(0,t.jsx)("td",{className:"px-3 py-1.5 text-xs text-mute",children:[e.httpOnly?"HttpOnly":"",e.secure?"Secure":"",e.sameSite?`SameSite=${e.sameSite}`:""].filter(Boolean).join(" · ")||"—"})]},a)})})]})})]})}var er=e.i(19656);let el={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 ei({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 eo({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 ed({headers:e}){let s=(0,B.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)(H.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 hidden here — see Cookies, and Request sent."})]})}function ec({body:e,contentType:s,truncated:a,url:n,base64:l}){let i=(0,B.useToast)(),d=function(e,t){let s=t.toLowerCase();if(s.startsWith("image/"))return"image";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),c="image"===d&&l?`data:${s.split(";")[0]};base64,${l}`:null,u=a||e.length>=16384,[h,m]=(0,r.useState)("pretty"),[p,x]=(0,r.useState)(!0),[f,b]=(0,r.useState)(""),[v,g]=(0,r.useState)(0),[j,y]=(0,r.useState)(!1),w=(0,r.useRef)(null),N=(0,r.useRef)(null);(0,r.useEffect)(()=>{m("image"===d?"preview":"pretty"),b(""),g(0)},[e,d]);let k=(0,r.useMemo)(()=>e?"raw"===h?e:function(e,t){if("json"!==t)return e;try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}(e,d):"",[e,h,d]),C=(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,f),[k,f]);function $(e){0!==C&&g(t=>(t+e+C)%C)}(0,r.useEffect)(()=>{let e=N.current?.querySelector("mark.current");e?.scrollIntoView({block:"center"})},[v,f,h]);let S=c?[{value:"preview",label:"Preview"},{value:"raw",label:"Raw"}]:[{value:"pretty",label:"Pretty"},{value:"raw",label:"Raw"},..."html"===d?[{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(),y(!0),window.setTimeout(()=>w.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:h,onChange:m,options:S}),(0,t.jsx)("span",{className:"rounded border border-line px-1.5 py-0.5 font-mono text-xs text-mute uppercase",children:d}),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:[j?(0,t.jsxs)("div",{className:"flex items-center gap-1 rounded-md border border-line bg-panel px-1.5",children:[(0,t.jsx)(U.Search,{size:12,className:"text-mute"}),(0,t.jsx)("input",{ref:w,value:f,"aria-label":"Find in body",placeholder:"Find",onChange:e=>{b(e.target.value),g(0)},onKeyDown:e=>{"Enter"===e.key&&$(e.shiftKey?-1:1),"Escape"===e.key&&(b(""),y(!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:f?`${C?v+1:0}/${C}`:""}),(0,t.jsx)(eu,{label:"Previous match",onClick:()=>$(-1),children:(0,t.jsx)(z,{size:12})}),(0,t.jsx)(eu,{label:"Next match",onClick:()=>$(1),children:(0,t.jsx)(A.ChevronDown,{size:12})})]}):(0,t.jsx)(eu,{label:"Find in body (Ctrl+F)",onClick:()=>{y(!0),window.setTimeout(()=>w.current?.focus(),0)},children:(0,t.jsx)(U.Search,{size:14})}),(0,t.jsx)(eu,{label:p?"Turn off line wrap":"Wrap long lines",pressed:p,onClick:()=>x(e=>!e),children:(0,t.jsx)(F,{size:14})}),(0,t.jsx)(eu,{label:"Copy body",onClick:()=>{navigator.clipboard.writeText(k),i("Body copied","success")},children:(0,t.jsx)(H.Copy,{size:14})}),(0,t.jsx)(eu,{label:"Download body",onClick:()=>{var e;return c&&l?(0,W.downloadBlob)(em(n,d,s),new Blob([Uint8Array.from(atob(l),e=>e.charCodeAt(0))],{type:s.split(";")[0]})):(0,W.downloadText)(em(n,d),k,"json"===(e=d)?"application/json":"html"===e?"text/html":"xml"===e?"application/xml":"text/plain")},children:(0,t.jsx)(O.Download,{size:14})})]})]}),"preview"===h&&c?(0,t.jsx)("div",{className:"flex min-h-[12rem] flex-1 items-center justify-center overflow-auto p-3",children:(0,t.jsx)("img",{src:c,alt:"Response image",className:"max-h-[32rem] max-w-full object-contain"})}):"preview"===h?(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:N,tabIndex:0,"aria-label":"Response body",className:`min-h-[12rem] flex-1 overflow-auto p-3 font-mono text-[13px] leading-5 text-ink ${p?"break-words whitespace-pre-wrap":"whitespace-pre"}`,children:f?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,f,v):"pretty"!==h||"json"!==d||u?k:function(e){let s=[],a=0;for(let n of e.matchAll(eh)){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 eu({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 eh=/("(?:\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*")(\s*:)?|\b(true|false|null)\b|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g;function em(e,t,s=""){let a="response";try{a=new URL(e).pathname.split("/").filter(Boolean).pop()||"response"}catch{}let n="json"===t?"json":"html"===t?"html":"xml"===t?"xml":"image"===t?/svg/.test(s)?"svg":s.split("/")[1]?.split(/[;+]/)[0]?.replace("jpeg","jpg")||"img":"txt";return`${a.replace(/[^\w.-]+/g,"_")}.${n}`}e.s(["ResponseViewer",0,function({result:e}){var s,a;let n,[l,i]=(0,r.useState)("body"),o=e.cookies??[],d=("cookies"!==l||o.length)&&("request"!==l||e.sent)&&("checks"!==l||(e.checks??[]).length)?l:"body",c=e.checks??[],u=c.filter(e=>e.ok).length,h=Object.keys(e.headers).length,m=(n=Object.keys(s=e.headers).find(e=>"content-type"===e.toLowerCase()))?s[n]??"":"",p=(0,r.useMemo)(()=>new TextEncoder().encode(e.body).length,[e.body]),x=!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:x?"Error":`${e.status} ${el[e.status]??""}`.trim()}),(0,t.jsx)(ei,{label:"Time",value:`${e.durationMs} ms`}),x?null:(0,t.jsx)(ei,{label:"Size",value:`${(0,er.formatBytes)(p)}${e.truncated?"+":""}`}),m?(0,t.jsx)(ei,{label:"Type",value:m.split(";")[0]??m}):null,c.length?(0,t.jsxs)("button",{type:"button",onClick:()=>i("checks"),className:`rounded-md border px-2 py-0.5 text-xs ${u===c.length?"border-ok/40 text-ok":"border-bad/40 text-bad"}`,children:[u===c.length?"✓":"✕"," ",u,"/",c.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)(eo,{message:e.error}):null,x&&e.sent?(0,t.jsxs)("details",{className:"mt-3 text-sm",children:[(0,t.jsx)("summary",{className:"cursor-pointer text-xs text-mute hover:text-ink",children:"What was sent"}),(0,t.jsx)("div",{className:"mt-2",children:(0,t.jsx)(ea,{sent:e.sent})})]}):null,x?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:d,onChange:i,items:[{id:"body",label:"Body"},{id:"headers",label:"Headers",badge:h||void 0},...o.length?[{id:"cookies",label:"Cookies",badge:o.length}]:[],...c.length?[{id:"checks",label:"Checks",badge:(0,t.jsxs)("span",{className:u===c.length?"text-ok":"text-bad",children:[u,"/",c.length]})}]:[],...e.sent?[{id:"request",label:"Request sent"}]:[]]}),(0,t.jsx)("div",{...(0,I.tabPanelProps)("response",d),className:"flex min-h-0 flex-1 flex-col pt-3",children:"body"===d?(0,t.jsx)(ec,{body:e.body,contentType:m,truncated:e.truncated,url:e.url,base64:e.bodyBase64}):"cookies"===d?(0,t.jsx)(en,{cookies:o}):"request"===d&&e.sent?(0,t.jsx)(ea,{sent:e.sent}):"checks"===d?(0,t.jsx)("ul",{className:"space-y-1.5",children:c.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.jsxs)("span",{className:"min-w-0",children:[(0,t.jsx)("span",{className:"block font-mono text-[13px] text-ink",children:e.name}),!e.ok&&e.detail?(0,t.jsx)("span",{className:"block text-xs text-mute",children:e.detail}):null]}),(0,t.jsx)("span",{className:`ml-auto shrink-0 text-xs ${e.ok?"text-ok":"text-bad"}`,children:e.ok?"pass":"fail"})]},s))}):(0,t.jsx)(ed,{headers:e.headers})})]})]})}],60566)},68228,65638,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(99112),a=e.i(78451),n=e.i(89932),r=e.i(36620),l=e.i(73436),i=e.i(99522);let o=(0,i.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 d=e.i(71189),c=e.i(43514),u=e.i(96659),h=e.i(87283),m=e.i(83067),p=e.i(39170),x=e.i(80707),f=e.i(56396);e.i(42674);var b=e.i(5305),v=e.i(65238),g=e.i(6278);let j=()=>globalThis.crypto?.randomUUID?.()??`env-${Date.now().toString(36)}`;function y({onClose:e}){let s=(0,f.useToast)(),a=(0,p.useConfirm)(),{environments:r,activeEnv:l,setActiveEnv:i,saveEnvironments:c,index:x}=(0,g.useWorkspace)(),[b,v]=(0,m.useState)(()=>structuredClone(r)),[k,C]=(0,m.useState)(l?.id??r[0]?.id??null),[$,S]=(0,m.useState)(!1),q=(0,m.useRef)(null),E=b.find(e=>e.id===k)??null,R=JSON.stringify(b)!==JSON.stringify(r);(0,m.useEffect)(()=>{let e=document.activeElement;return q.current?.querySelector("input,button")?.focus(),()=>e?.focus()},[]);let T=(e,t)=>v(s=>s.map(s=>s.id===e?{...s,...t}:s));function M(e){let t=e?{id:j(),name:`${e.name} copy`,variables:structuredClone(e.variables)}:{id:j(),name:b.length?`Environment ${b.length+1}`:"DEV",variables:[{key:"baseUrl",value:"",secret:!1}]};v(e=>[...e,t]),C(t.id)}async function L(){(!R||await a({title:"Discard changes to environments?",confirmLabel:"Discard",tone:"danger"}))&&e()}async function P(){S(!0);try{await c(b),l&&!b.some(e=>e.id===l.id)&&i(null),s("Environments saved","success"),e()}catch(e){s(e instanceof Error?e.message:"Could not save environments","error")}finally{S(!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 L(),children:(0,t.jsxs)("div",{ref:q,role:"dialog","aria-modal":"true","aria-label":"Environments",onKeyDown:e=>"Escape"===e.key&&void L(),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 L(),children:(0,t.jsx)(h.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:()=>C(e.id),"aria-current":e.id===k?"true":void 0,className:`block w-full truncate rounded-md px-2 py-1.5 text-left text-sm ${e.id===k?"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:()=>M(),className:"mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline",children:[(0,t.jsx)(d.Plus,{size:12,"aria-hidden":!0})," New environment"]})]}),(0,t.jsxs)("section",{className:"min-h-0 space-y-4 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=>T(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:()=>M(E),children:[(0,t.jsx)(n.Copy,{size:13})," Duplicate"]}),(0,t.jsxs)("button",{type:"button",className:"btn btn-danger py-1.5 text-xs",onClick:()=>{v(e=>e.filter(e=>e.id!==E.id)),C(b.find(e=>e.id!==E.id)?.id??null)},children:[(0,t.jsx)(u.Trash2,{size:13})," Delete"]})]}),(0,t.jsx)(N,{vars:E.variables,onPatch:(e,t)=>E&&T(E.id,{variables:E.variables.map((s,a)=>a===e?{...s,...t}:s)}),onChange:e=>T(E.id,{variables:e})}),(0,t.jsxs)("p",{className:"flex items-start gap-1.5 text-xs text-mute",children:[(0,t.jsx)(o,{size:12,className:"mt-0.5 shrink-0","aria-hidden":!0}),x?.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:()=>M(),children:[(0,t.jsx)(d.Plus,{size:14})," New environment"]})})]}),(0,t.jsx)(w,{onCopied:e=>s(`Copied ${e}`,"success")})]})]}),(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 L(),children:"Cancel"}),(0,t.jsx)("button",{type:"button",className:"btn btn-primary text-sm",disabled:!R||$,onClick:()=>void P(),children:"Save environments"})]})]})})}function w({onCopied:e}){return(0,t.jsxs)("details",{className:"rounded-md border border-line bg-panel-2/40 px-3 py-2 text-sm",children:[(0,t.jsxs)("summary",{className:"cursor-pointer text-xs font-medium text-ink",children:["Built-in values ",(0,t.jsx)("span",{className:"font-normal text-mute",children:"— made anew for every request, in load tests too"})]}),(0,t.jsx)("ul",{className:"mt-2 space-y-1",children:s.BUILTIN_VALUES.map(s=>(0,t.jsxs)("li",{className:"flex items-center gap-2 text-xs",children:[(0,t.jsxs)("button",{type:"button",title:"Copy",onClick:()=>void navigator.clipboard?.writeText(s.example).then(()=>e(s.example)),className:"inline-flex shrink-0 items-center gap-1 rounded border border-line px-1.5 py-0.5 font-mono text-accent hover:border-accent",children:[s.example,(0,t.jsx)(n.Copy,{size:11,"aria-hidden":!0})]}),(0,t.jsx)("span",{className:"text-mute",children:s.description})]},s.name))}),(0,t.jsxs)("p",{className:"mt-2 text-xs text-mute",children:["In a JSON body put them in quotes, like ",(0,t.jsx)("code",{className:"font-mono text-ink",children:'"id": "{{$uuid}}"'}),"."]})]})}function N({vars:e,onPatch:s,onChange:a}){let[n,i]=(0,m.useState)(new Set),o=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((d,c)=>{let u=d.key&&!/^[A-Za-z_][\w.-]*$/.test(d.key)||o.has(d.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":u||void 0,title:u?"Letters, digits, _ . - ; must start with a letter or _ ; must be unique":void 0,value:d.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 ${u?"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:d.secret&&!n.has(c)?"password":"text",autoComplete:"off",value:d.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"}),d.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.EyeOff,{size:13}):(0,t.jsx)(r.Eye,{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:d.secret,onChange:e=>s(c,{secret:e.target.checked}),className:"accent-[var(--accent)]"}),"secret"]}),(0,t.jsx)("button",{type:"button","aria-label":`Remove ${d.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)(h.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)(d.Plus,{size:12,"aria-hidden":!0})," Add variable"]})]})}e.s(["EnvironmentBar",0,function({drafts:e,collections:s=[]}){let{environments:n,activeEnv:r,setActiveEnv:l,vars:i,savedValues:o,clearSavedValues:d}=(0,g.useWorkspace)(),u=Object.keys(o),[h,p]=(0,m.useState)(!1),f=(0,m.useMemo)(()=>{let t=new Set;for(let s of e){let e=new Set((0,b.draftRuntimeNames)(s)),n=[s.url,s.bodyText,s.token,s.username,s.password,s.apiValue,...s.params.map(e=>e.value),...s.headers.map(e=>e.value)].join(" ");(0,a.findVariables)(n).forEach(s=>!e.has(s)&&t.add(s))}return[...t]},[e]),j=(0,v.useFolderVarNames)(s),w=f.filter(e=>!(e in i)&&!j.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)(c.Settings2,{size:12,"aria-hidden":!0})," Manage"]}),f.length>0?w.length?(0,t.jsxs)("span",{className:"text-warn",role:"status",children:[w.map(e=>`{{${e}}}`).join(", ")," not defined",r?` in ${r.name}`:" — pick an environment"]}):(0,t.jsxs)("span",{className:"text-mute",children:["Uses ",f.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:d,className:"text-mute underline-offset-2 hover:text-ink hover:underline",children:"Clear"})]}):null,h?(0,t.jsx)(y,{onClose:()=>p(!1)}):null]})},"VariableTable",0,N],68228);var k=e.i(95486),C=e.i(60961);let $=(0,i.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"}]]),S=(0,i.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"}]]),q=(0,i.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"}]]),E=(0,i.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 R=e.i(19286),T=e.i(81538),M=e.i(3792),L=e.i(88293),P=e.i(50804),A=e.i(67217),D=e.i(41997),z=e.i(37837),H=e.i(27813),O=e.i(36e3),U=e.i(13318);function F({path:e,onClose:s}){let n=(0,f.useToast)(),{refresh:r}=(0,g.useWorkspace)(),[l,i]=(0,m.useState)(null),[o,d]=(0,m.useState)([]),[c,u]=(0,m.useState)([]),[p,x]=(0,m.useState)("auth"),[b,j]=(0,m.useState)(!1);async function y(){if(l&&!b){j(!0);try{await v.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"),s()}catch(e){n(e instanceof Error?e.message:"Could not save","error")}finally{j(!1)}}}(0,m.useEffect)(()=>{let t=!0;return Promise.all([v.folderApi.get(e),v.folderApi.chain((0,a.parentFolder)(e))]).then(([e,s])=>{t&&(i(e.settings),d(e.secretsMissing??[]),u(s))}).catch(e=>{t&&(n(e instanceof Error?e.message:"Could not open the folder","error"),i((0,a.emptyFolderSettings)()))}),()=>{t=!1}},[e,n]);let w=[...c].reverse().find(e=>"inherit"!==e.settings.auth.authMode),k=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&&s(),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-labelledby":"folder-settings-title",onKeyDown:e=>"Escape"===e.key&&s(),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:s,children:(0,t.jsx)(h.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:p,onChange:x,items:[{id:"auth",label:"Auth"},{id:"headers",label:"Headers",badge:k.headers||void 0},{id:"variables",label:"Variables",badge:k.variables||void 0}]}),(0,t.jsxs)("div",{...(0,U.tabPanelProps)("folder-settings",p),className:"pt-4",children:["auth"===p?(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:w&&"none"!==w.settings.auth.authMode?(0,t.jsxs)(t.Fragment,{children:["Passes on the ",(0,t.jsx)("span",{className:"text-ink",children:(0,D.authModeLabel)(w.settings.auth.authMode)})," of"," ",(0,t.jsx)("span",{className:"text-ink",children:w.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"===p?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(O.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"===p?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(N,{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)(H.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:s,disabled:b,children:"Cancel"}),(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",onClick:()=>void y(),disabled:!l||b,children:[b?(0,t.jsx)(H.Loader2,{size:14,className:"animate-spin"}):null,"Save folder settings"]})]})]})})}var I=e.i(14168);let B={GET:"text-ok",POST:"text-warn",PUT:"text-accent",PATCH:"text-accent",DELETE:"text-bad"};function W({activeId:e,onOpen:s,allowDelete:n=!0,newFolder:r,onNewFolderDone:l}){let i=(0,f.useToast)(),o=(0,p.useConfirm)(),{index:d,refresh:c}=(0,g.useWorkspace)(),[h,x]=(0,m.useState)(""),[b,j]=(0,m.useState)(new Set),[y,w]=(0,m.useState)(null),[N,$]=(0,m.useState)(null),q=d?.requests??[],E=d?.folders??[],T=h.trim().toLowerCase(),z=(0,m.useMemo)(()=>T?q.filter(e=>`${e.name} ${e.collection} ${e.url} ${e.method}`.toLowerCase().includes(T)):q,[q,T]),H=(0,m.useMemo)(()=>(function(e,t,s){let n={path:"",name:"",folders:[],requests:[],summary:null},r=new Map([["",n]]),l=e=>{let t=r.get(e);if(t)return t;let s={path:e,name:(0,a.folderName)(e),folders:[],requests:[],summary:null};return r.set(e,s),l((0,a.parentFolder)(e)).folders.push(s),s};if(s)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})(z,E,!T),[z,E,T]);async function O(e){try{let t=await g.workspaceApi.get(e);s(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 U(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 g.workspaceApi.remove(e.id).catch(()=>void 0),await c())}async function J(e){if(w(null),l?.(),!y)return;let t=e.trim();if(t)try{if("new"===y.kind){let e=(0,a.folderPath)(y.parent?`${y.parent}/${t}`:t);await v.folderApi.save(e,(0,a.emptyFolderSettings)()),j(e=>{let t=new Set(e);return t.delete(y.parent),t})}else{let e=(0,a.folderPath)(t.includes("/")?t:(0,a.parentFolder)(y.path)?`${(0,a.parentFolder)(y.path)}/${t}`:t);e!==y.path&&await v.folderApi.move(y.path,e)}await c()}catch(e){i(e instanceof Error?e.message:"Could not do that","error")}}async function K(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 v.folderApi.remove(e),await c()}catch(e){i(e instanceof Error?e.message:"Could not delete the folder","error")}}(0,m.useEffect)(()=>{r&&w({kind:"new",parent:""})},[r]);let G=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 O(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 ${B[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 U(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)(u.Trash2,{size:12})}):null]},s.id))}),X=e=>{var s;let a=b.has(e.path)&&!T,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)(V,{initial:e.path,label:`New name for ${e.path}`,onDone:e=>void J(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)(C.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)(S,{size:12,"aria-hidden":!0,className:"shrink-0"}),(0,t.jsx)("span",{className:"truncate",children:e.name}),e.summary?.auth?(0,t.jsx)(R.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)(P.default,{href:(0,I.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)(M.Play,{size:12})}),(0,t.jsx)(_,{path:e.path,onSettings:()=>$(e.path),onNewInside:()=>w({kind:"new",parent:e.path}),onRename:()=>w({kind:"rename",path:e.path}),onDelete:()=>void K(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)(V,{initial:"",label:`New folder in ${e.path}`,onDone:e=>void J(e)}):null,e.folders.map(X),G(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)(L.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:h,onChange:e=>x(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)(V,{initial:"",label:"New folder",onDone:e=>void J(e),hint:"Use / for a folder inside another: Orders/Admin"}):null,0===q.length&&0===E.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:A.openImport,className:"text-accent hover:underline",children:"Import your requests"})]})]}):T&&0===z.length?(0,t.jsx)("p",{className:"px-1 py-4 text-xs text-mute",children:"Nothing matches."}):(0,t.jsxs)(t.Fragment,{children:[H.folders.map(X),G(H.requests)]})]}),N?(0,t.jsx)(F,{path:N,onClose:()=>$(null)}):null]})}function V({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)(T.MoreHorizontal,{size:13})}),(0,t.jsx)(z.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)(S,{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)(W,{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)($,{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)(q,{size:14})}),(0,t.jsx)("button",{type:"button",onClick:A.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)(E,{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)(h.X,{size:14})})]})]}),(0,t.jsx)(W,{activeId:e,onOpen:s,newFolder:r,onNewFolderDone:()=>l(!1)})]})},"SaveRequestForm",0,function({initial:e,onSave:s,onCancel:a}){let{index:n}=(0,g.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)(h.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])}]);
|