apitestcenter 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +8 -1
  2. package/dist/THIRD-PARTY-NOTICES-UI.txt +3239 -0
  3. package/dist/THIRD-PARTY-NOTICES.txt +1484 -1
  4. package/dist/cli.mjs +107819 -49664
  5. package/dist/ui/404/index.html +1 -0
  6. package/dist/ui/404.html +1 -0
  7. package/dist/ui/__next.__PAGE__.txt +22 -0
  8. package/dist/ui/__next._full.txt +20 -0
  9. package/dist/ui/__next._tree.txt +6 -0
  10. package/dist/ui/_next/static/chunks/0-898cb98enjv.css +3 -0
  11. package/dist/ui/_next/static/chunks/02myfb0nlri-z.js +119 -0
  12. package/dist/ui/_next/static/chunks/08w_94tt7q8fk.js +1 -0
  13. package/dist/ui/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
  14. package/dist/ui/_next/static/chunks/0ezgetg09gtvn.js +1 -0
  15. package/dist/ui/_next/static/chunks/0kfr8kv4cj_kv.js +1 -0
  16. package/dist/ui/_next/static/chunks/0txpfp028djv6.js +291 -0
  17. package/dist/ui/_next/static/chunks/0vkcbl8nakdh1.js +2 -0
  18. package/dist/ui/_next/static/chunks/13nvl7bxr0ra-.js +1 -0
  19. package/dist/ui/_next/static/chunks/1l0uy37izo74u.js +22 -0
  20. package/dist/ui/_next/static/chunks/1w_q4qvvuinj2.js +1 -0
  21. package/dist/ui/_next/static/chunks/2idsynwg5lkk7.js +51 -0
  22. package/dist/ui/_next/static/chunks/2lw9bsrnh8k4u.js +1 -0
  23. package/dist/ui/_next/static/chunks/2nxnxp6p-40kg.js +1 -0
  24. package/dist/ui/_next/static/chunks/37izghagcat04.js +1 -0
  25. package/dist/ui/_next/static/chunks/3ad2zh-p8_xhv.js +59 -0
  26. package/dist/ui/_next/static/chunks/3eqn1h2-qx894.css +1 -0
  27. package/dist/ui/_next/static/chunks/3fb2986f7qg9x.js +1 -0
  28. package/dist/ui/_next/static/chunks/41ad2nnyaestx.js +31 -0
  29. package/dist/ui/_next/static/chunks/turbopack-2kiaj9_7vlslw.js +1 -0
  30. package/dist/ui/_next/static/lBYayPKoT6YJhgfHFuw6O/_buildManifest.js +11 -0
  31. package/dist/ui/_next/static/lBYayPKoT6YJhgfHFuw6O/_clientMiddlewareManifest.js +1 -0
  32. package/dist/ui/_next/static/lBYayPKoT6YJhgfHFuw6O/_ssgManifest.js +1 -0
  33. package/dist/ui/_next/static/media/02263ebadd758ea4-s.29yke99gs9qpn.woff2 +0 -0
  34. package/dist/ui/_next/static/media/03fc1b4a8d284b5e-s.p.0wiir8udbzjvx.woff2 +0 -0
  35. package/dist/ui/_next/static/media/1bcd0e671759a44c-s.2qt3tdwt-y9x_.woff2 +0 -0
  36. package/dist/ui/_next/static/media/2fe89d53234c61d4-s.1u30mmyq6lnsd.woff2 +0 -0
  37. package/dist/ui/_next/static/media/57215795b8570f5c-s.2rixgazldzomk.woff2 +0 -0
  38. package/dist/ui/_next/static/media/59b15b4bcd7b1eb5-s.2vemzm0itqzfy.woff2 +0 -0
  39. package/dist/ui/_next/static/media/5e05ae5b48faa55e-s.1yd4_i3e35931.woff2 +0 -0
  40. package/dist/ui/_next/static/media/68757d6cddeff913-s.1i-sca43-qwng.woff2 +0 -0
  41. package/dist/ui/_next/static/media/7fea77d1d19108bf-s.2y65deuc30pmy.woff2 +0 -0
  42. package/dist/ui/_next/static/media/90c51ce8fb754fe8-s.02z5rrbg5nt92.woff2 +0 -0
  43. package/dist/ui/_next/static/media/99e609270109b47d-s.p.40sczeszzbjw1.woff2 +0 -0
  44. package/dist/ui/_next/static/media/a7afbb44bec2bb18-s.1qc6dx89jd2qv.woff2 +0 -0
  45. package/dist/ui/_next/static/media/e15f58668ad64cb8-s.3cvcemwuzoywn.woff2 +0 -0
  46. package/dist/ui/_next/static/media/e390973e931a41c5-s.0rgnxg2b64rzs.woff2 +0 -0
  47. package/dist/ui/_next/static/media/e532fa1b9921e1cd-s.3cb5lpr2l6xud.woff2 +0 -0
  48. package/dist/ui/_next/static/media/effe91970fc4db64-s.p.0oace-s_gkfks.woff2 +0 -0
  49. package/dist/ui/_not-found/__next._full.txt +17 -0
  50. package/dist/ui/_not-found/__next._not-found.__PAGE__.txt +23 -0
  51. package/dist/ui/_not-found/__next._tree.txt +2 -0
  52. package/dist/ui/_not-found/index.html +1 -0
  53. package/dist/ui/_not-found/index.txt +17 -0
  54. package/dist/ui/compare/__next._full.txt +22 -0
  55. package/dist/ui/compare/__next._tree.txt +6 -0
  56. package/dist/ui/compare/__next.compare.__PAGE__.txt +25 -0
  57. package/dist/ui/compare/index.html +1 -0
  58. package/dist/ui/compare/index.txt +22 -0
  59. package/dist/ui/history/__next._full.txt +25 -0
  60. package/dist/ui/history/__next._tree.txt +6 -0
  61. package/dist/ui/history/__next.history.__PAGE__.txt +28 -0
  62. package/dist/ui/history/index.html +1 -0
  63. package/dist/ui/history/index.txt +25 -0
  64. package/dist/ui/index.html +1 -0
  65. package/dist/ui/index.txt +20 -0
  66. package/dist/ui/preview/__next._full.txt +25 -0
  67. package/dist/ui/preview/__next._tree.txt +6 -0
  68. package/dist/ui/preview/__next.preview.__PAGE__.txt +28 -0
  69. package/dist/ui/preview/index.html +1 -0
  70. package/dist/ui/preview/index.txt +25 -0
  71. package/dist/ui/suite/__next._full.txt +21 -0
  72. package/dist/ui/suite/__next._tree.txt +5 -0
  73. package/dist/ui/suite/__next.suite.__PAGE__.txt +24 -0
  74. package/dist/ui/suite/index.html +1 -0
  75. package/dist/ui/suite/index.txt +21 -0
  76. package/dist/ui/tests/__next._full.txt +21 -0
  77. package/dist/ui/tests/__next._tree.txt +5 -0
  78. package/dist/ui/tests/__next.tests.__PAGE__.txt +24 -0
  79. package/dist/ui/tests/index.html +1 -0
  80. package/dist/ui/tests/index.txt +21 -0
  81. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,69578,2603,e=>{"use strict";e.s(["CommandPalette",()=>b,"OPEN_REQUEST_EVENT",()=>x,"OPEN_REQUEST_KEY",()=>p],69578);var t=e.i(61666),s=e.i(78739),a=e.i(7641),n=e.i(67217),r=e.i(56931),l=e.i(5831),i=e.i(86856),o=e.i(88293),c=e.i(48317),d=e.i(46443),u=e.i(83067);function h(){let[e,t]=(0,u.useState)("Ctrl");return(0,u.useEffect)(()=>t("u">typeof navigator&&/Mac|iPhone|iPad/.test(navigator.platform)?"⌘":"Ctrl"),[]),e}e.s(["useModKey",0,h,"useShortcuts",0,function(e){let t=(0,u.useRef)(e);t.current=e,(0,u.useEffect)(()=>{let e=e=>{if(document.querySelector("[aria-modal='true']"))return;let s=e.ctrlKey||e.metaKey;if(s&&!e.shiftKey&&"s"===e.key.toLowerCase()&&t.current.save){e.preventDefault(),t.current.save();return}if(s&&"Enter"===e.key){e.preventDefault(),e.shiftKey?t.current.run?.():t.current.send?.();return}if("/"===e.key&&!s&&!e.altKey){let s=e.target;!(s&&(s.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(s.tagName)))&&t.current.focusUrl&&(e.preventDefault(),t.current.focusUrl())}};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[])}],2603);var m=e.i(6278);let p="apitestcenter-open-request",x="atc:open-request";function f(e){window.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter",ctrlKey:!0,metaKey:!0,shiftKey:e,bubbles:!0}))}function b(){let e=(0,d.useRouter)(),b=(0,d.usePathname)(),g=h(),{setTheme:v}=(0,c.useTheme)(),{index:y,environments:w,setActiveEnv:j,activeEnv:k}=(0,m.useWorkspace)(),[N,C]=(0,u.useState)(!1),[S,E]=(0,u.useState)(""),[T,A]=(0,u.useState)(0),L=(0,u.useRef)(null),P=(0,u.useRef)(null);(0,u.useEffect)(()=>{let e=e=>{(e.ctrlKey||e.metaKey)&&"k"===e.key.toLowerCase()&&(e.preventDefault(),C(e=>!e))},t=()=>C(!0);return window.addEventListener("keydown",e),window.addEventListener("atc:palette",t),()=>{window.removeEventListener("keydown",e),window.removeEventListener("atc:palette",t)}},[]),(0,u.useEffect)(()=>{if(!N)return;E(""),A(0);let e=document.activeElement;return window.setTimeout(()=>L.current?.focus(),0),()=>e?.focus?.()},[N]);let I=(0,u.useMemo)(()=>{let t=e=>()=>{C(!1),window.setTimeout(e,0)},i=s=>t(()=>e.push(s)),o="/"===b||"/compare"===b,c=[{id:"go-test",group:"Go to",label:"Test API",run:i("/")},{id:"go-suite",group:"Go to",label:"Run collection",run:i("/suite")},{id:"go-compare",group:"Go to",label:"Compare",run:i("/compare")},{id:"go-history",group:"Go to",label:"History",run:i("/history")},{id:"go-open",group:"Go to",label:"Open report",run:i("/preview")},{id:"import",group:"Actions",label:"Import from Postman or OpenAPI",run:t(n.openImport)},{id:"certificates",group:"Actions",label:"Client certificates (mutual TLS)",run:t(r.openCertificates)},{id:"help",group:"Help",label:"Help: what do these words mean?",run:t(a.openHelp)},{id:"about",group:"Help",label:"About APITestCenter — version and updates",run:t(s.openAbout)},{id:"tour",group:"Help",label:"Take the 1-minute tour",run:t(()=>"/"===b?(0,l.startTour)():(e.push("/"),window.setTimeout(l.startTour,900)))}];for(let s of(o&&c.push({id:"send",group:"Actions",label:"Send request",hint:`${g}+Enter`,run:t(()=>f(!1))},{id:"run",group:"Actions",label:"/compare"===b?"Compare load":"Run load test",hint:`${g}+Shift+Enter`,run:t(()=>f(!0))}),y?.requests??[]))c.push({id:`req-${s.id}`,group:"Saved requests",label:`${s.collection?`${s.collection} / `:""}${s.name}`,hint:s.method,run:t(()=>{try{sessionStorage.setItem(p,s.id)}catch{}"/"===b?window.dispatchEvent(new Event(x)):e.push("/")})});for(let e of(c.push({id:"env-none",group:"Environment",label:"Use no environment",hint:k?void 0:"current",run:t(()=>j(null))}),w))c.push({id:`env-${e.id}`,group:"Environment",label:`Use environment: ${e.name}`,hint:k?.id===e.id?"current":`${e.variables.length} vars`,run:t(()=>j(e.id))});for(let e of["system","light","dark"])c.push({id:`theme-${e}`,group:"Theme",label:`Theme: ${e[0].toUpperCase()}${e.slice(1)}`,run:t(()=>v(e))});return c},[y,w,k,b,e,g,j,v]),R=(0,u.useMemo)(()=>I.map(e=>({item:e,s:function(e,t){if(!t)return 1;let s=e.toLowerCase(),a=t.toLowerCase(),n=0,r=0;for(let e of a){let t=s.indexOf(e,n);if(t<0)return 0;r+=0===t||/[\s/·:-]/.test(s[t-1]??"")?3:t===n?2:1,n=t+1}return r}(`${e.group} ${e.label}`,S)})).filter(e=>e.s>0).sort((e,t)=>S?t.s-e.s:0).map(e=>e.item).slice(0,50),[I,S]);return((0,u.useEffect)(()=>{P.current?.querySelector(`[data-index="${T}"]`)?.scrollIntoView({block:"nearest"})},[T]),N)?(0,t.jsx)("div",{className:"fixed inset-0 z-[60] flex items-start justify-center bg-black/50 p-4 pt-[12vh] backdrop-blur-sm",onMouseDown:e=>e.target===e.currentTarget&&C(!1),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-label":"Command palette",className:"w-full max-w-xl overflow-hidden rounded-xl border border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 border-b border-line px-3",children:[(0,t.jsx)(o.Search,{size:16,className:"text-mute","aria-hidden":!0}),(0,t.jsx)("input",{ref:L,value:S,role:"combobox","aria-expanded":"true","aria-controls":"palette-list","aria-activedescendant":R[T]?`palette-${R[T].id}`:void 0,onChange:e=>{E(e.target.value),A(0)},onKeyDown:e=>{"Escape"===e.key?C(!1):"ArrowDown"===e.key?(e.preventDefault(),A(e=>Math.min(R.length-1,e+1))):"ArrowUp"===e.key?(e.preventDefault(),A(e=>Math.max(0,e-1))):"Enter"===e.key&&(e.preventDefault(),R[T]?.run())},placeholder:"Go to a page, open a saved request, switch environment…",className:"min-w-0 flex-1 bg-transparent py-3 text-sm text-ink outline-none placeholder:text-mute"}),(0,t.jsx)("span",{className:"kbd",children:"Esc"})]}),(0,t.jsxs)("ul",{id:"palette-list",ref:P,role:"listbox","aria-label":"Commands",className:"max-h-[50vh] overflow-auto p-1",children:[0===R.length?(0,t.jsx)("li",{className:"px-3 py-6 text-center text-sm text-mute",children:"No matches."}):null,R.map((e,s)=>{let a=0===s||R[s-1].group!==e.group;return(0,t.jsxs)("li",{children:[a?(0,t.jsx)("div",{className:"px-2 pt-2 pb-1 text-[11px] font-medium tracking-wide text-mute uppercase",children:e.group}):null,(0,t.jsxs)("div",{id:`palette-${e.id}`,role:"option","aria-selected":s===T,"data-index":s,onMouseMove:()=>A(s),onClick:()=>e.run(),className:`flex cursor-pointer items-center justify-between gap-3 rounded-md px-2.5 py-2 text-sm ${s===T?"bg-accent-dim text-ink":"text-ink"}`,children:[(0,t.jsx)("span",{className:"min-w-0 truncate",children:e.label}),e.hint?(0,t.jsx)("span",{className:"shrink-0 font-mono text-xs text-mute",children:e.hint}):null]})]},e.id)})]}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 border-t border-line px-3 py-2 text-xs text-mute",children:[(0,t.jsx)(i.Command,{size:12,"aria-hidden":!0})," ",(0,t.jsx)("span",{className:"kbd",children:g}),"+",(0,t.jsx)("span",{className:"kbd",children:"K"})," anywhere · ↑↓ to move · Enter to run"]})]})}):null}},78739,8055,e=>{"use strict";var t=e.i(61666),s=e.i(17118),a=e.i(75117),n=e.i(80190),r=e.i(20621),l=e.i(27813),i=e.i(458),o=e.i(49913),c=e.i(42709),d=e.i(87283),u=e.i(83067),h=e.i(56396),m=e.i(20054),p=e.i(59180);let x="atc:about",f=[{href:"https://apitestcenter.com/docs/",label:"User guide — how everything works"},{href:"https://apitestcenter.com/whats-new.html",label:"What's new in each version"},{href:"https://apitestcenter.com",label:"apitestcenter.com"},{href:"https://apitestcenter.com/privacy.html",label:"Privacy"},{href:"mailto:support@apitestcenter.com",label:"Report a problem — support@apitestcenter.com"}];function b({status:e}){if(!e)return(0,t.jsx)("p",{className:"text-sm text-mute",children:"Updates are checked by the desktop app. This copy runs in a browser."});switch(e.state){case"unsupported":return(0,t.jsx)("p",{className:"text-sm text-mute",children:"store"===e.reason?"This copy comes from the Microsoft Store, which keeps it up to date.":"off"===e.reason?"Update checks are turned off on this computer (ATC_NO_UPDATE).":"This is a development build; it does not update itself."});case"idle":return(0,t.jsx)("p",{className:"text-sm text-mute",children:"Checks for a new version shortly after opening and every 6 hours."});case"checking":return(0,t.jsxs)("p",{className:"flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)(l.Loader2,{size:14,className:"animate-spin text-accent"})," Checking for a new version…"]});case"current":return(0,t.jsxs)("p",{className:"flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)(s.CheckCircle2,{size:14,className:"text-ok"})," You have the latest version."]});case"available":return(0,t.jsxs)("p",{className:"text-sm text-ink",children:["Version ",e.version," is available. Download it from apitestcenter.com — your tests and history stay as they are."]});case"downloading":return(0,t.jsxs)("div",{className:"space-y-1.5",children:[(0,t.jsxs)("p",{className:"flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)(l.Loader2,{size:14,className:"animate-spin text-accent"})," Downloading version ",e.version,"… ",e.percent,"%"]}),(0,t.jsx)("div",{className:"h-1.5 overflow-hidden rounded bg-panel-2",children:(0,t.jsx)("div",{className:"h-full bg-accent",style:{width:`${e.percent}%`}})})]});case"ready":return(0,t.jsxs)("p",{className:"text-sm text-ink",children:["Version ",e.version," is ready. Restart to finish updating — or it updates the next time you close the app."]});case"error":return(0,t.jsxs)("p",{className:"flex items-start gap-2 text-sm text-ink",children:[(0,t.jsx)(c.TriangleAlert,{size:14,className:"mt-0.5 shrink-0 text-warn"})," ",e.message]})}}e.s(["AboutDialog",0,function(){let e=(0,h.useToast)(),{appVersion:s,k6Label:l,k6Ready:c,dataDir:g,online:v}=(0,m.useEngineHealth)(),[y,w]=(0,u.useState)(!1),[j,k]=(0,u.useState)(null),N=(0,u.useRef)(null),C=window.atcDesktop??null;if((0,u.useEffect)(()=>{let e=()=>w(!0);window.addEventListener(x,e);let t=C?.onUpdateStatus(k);return()=>{window.removeEventListener(x,e),t?.()}},[C]),(0,u.useEffect)(()=>{if(!y)return;C?.updateStatus().then(e=>e&&k(e)),window.setTimeout(()=>N.current?.focus(),0);let e=e=>"Escape"===e.key&&w(!1);return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[y,C]),!y)return null;let S=j?.state==="checking"||j?.state==="downloading",E=C&&j&&"unsupported"!==j.state&&"ready"!==j.state;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&&w(!1),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-labelledby":"about-title",className:"w-full max-w-lg rounded-xl border border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-center gap-3 border-b border-line px-5 py-4",children:[(0,t.jsx)("span",{className:"grid h-9 w-9 shrink-0 place-items-center rounded-lg bg-accent-dim text-xs font-semibold tracking-wider text-accent","aria-hidden":!0,children:"ATC"}),(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{id:"about-title",className:"text-base font-medium text-ink",children:"APITestCenter"}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Version ",(0,t.jsx)("span",{className:"font-mono text-ink",children:s&&"dev"!==s?s:"development build"})," · ",v?c?l:"k6 not found":"engine starting…"]})]}),(0,t.jsx)("button",{ref:N,type:"button",onClick:()=>w(!1),"aria-label":"Close",className:"ml-auto self-start rounded p-1 text-mute hover:text-ink",children:(0,t.jsx)(d.X,{size:16})})]}),(0,t.jsxs)("section",{className:"space-y-3 border-b border-line px-5 py-4",children:[(0,t.jsx)("h3",{className:"text-xs font-medium tracking-wide text-mute uppercase",children:"Updates"}),(0,t.jsx)(b,{status:C?j:null}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[E?(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1.5 text-sm",disabled:S,onClick:async()=>{k({state:"checking",canInstall:!!j&&"canInstall"in j&&j.canInstall});let e=await C.checkForUpdates().catch(()=>null);e&&k(e)},children:[(0,t.jsx)(i.RefreshCw,{size:14,className:S?"animate-spin":""})," Check for updates"]}):null,j?.state==="ready"?(0,t.jsxs)("button",{type:"button",className:"btn btn-primary py-1.5 text-sm",onClick:()=>void C?.restartToUpdate(),children:[(0,t.jsx)(o.RotateCw,{size:14})," Restart and update"]}):null,j?.state==="available"||j?.state==="error"&&C?(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1.5 text-sm",onClick:()=>void C?.openDownloadPage(),children:[(0,t.jsx)(a.Download,{size:14})," Open the download page"]}):null]})]}),(0,t.jsxs)("section",{className:"space-y-2 border-b border-line px-5 py-4",children:[(0,t.jsx)("h3",{className:"text-xs font-medium tracking-wide text-mute uppercase",children:"Your files"}),(0,t.jsx)("p",{className:"text-sm text-mute",children:"Saved requests, environments, and history are plain files on this computer:"}),(0,t.jsx)("p",{className:"truncate rounded-md bg-panel-2 px-2 py-1.5 font-mono text-xs text-ink",title:g,children:g??(v?"…":"Waiting for the engine to start…")}),(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1.5 text-sm",disabled:!g,onClick:()=>p.historyApi.reveal().catch(t=>e(t instanceof Error?t.message:"Could not open the folder","error")),children:[(0,t.jsx)(r.FolderOpen,{size:14})," Open folder"]})]}),(0,t.jsxs)("section",{className:"px-5 py-4",children:[(0,t.jsx)("ul",{className:"space-y-1.5 text-sm",children:f.map(e=>(0,t.jsx)("li",{children:(0,t.jsxs)("a",{href:e.href,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 text-accent hover:underline",children:[e.label," ",(0,t.jsx)(n.ExternalLink,{size:12,"aria-hidden":!0})]})},e.href))}),(0,t.jsx)("p",{className:"mt-3 text-xs text-mute",children:"© 2026 Ratul Roy. Free to use. Includes open-source software such as Grafana k6 (AGPL-3.0); the full list ships with the app as THIRD-PARTY-NOTICES.txt."})]})]})})},"openAbout",0,function(){window.dispatchEvent(new Event(x))}],78739);let g=(0,e.i(99522).default)("compass",[["path",{d:"m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z",key:"9ktpf1"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]]);e.s(["Compass",0,g],8055)},89142,5831,e=>{"use strict";e.s(["GLOSSARY",0,[{group:"Reading results",term:"Response time",tech:"p95 latency",text:"How long requests took. “p95 200 ms” means 95 of every 100 requests finished within 200 ms. It is a better guide than the average, because people notice the slow ones."},{group:"Reading results",term:"Typical response time",tech:"p50 · median",text:"Half of the requests were faster than this, half slower."},{group:"Reading results",term:"Slowest responses",tech:"p99 · max",text:"p99: the slowest 1 in 100 requests took at least this long. Max: the single slowest one."},{group:"Reading results",term:"Requests per second",tech:"throughput · RPS",text:"How many requests the API answered each second. Higher is better, as long as response time stays reasonable."},{group:"Reading results",term:"Failed requests",tech:"error rate",text:"The share of requests that got no answer, or an error status (400 or higher)."},{group:"Reading results",term:"Requests not sent",tech:"dropped iterations",text:"In request-rate tests: requests that could not start on time because every simulated user was still waiting for an answer. A sign the API — or this computer — could not keep up."},{group:"Reading results",term:"User satisfaction score",tech:"Apdex",text:"From 0 to 1. Counts answers that were fast (within your response-time goal) and ones that were slow but bearable (within 4×). 1 means everyone would be happy."},{group:"Reading results",term:"Server time",tech:"TTFB · time to first byte",text:"From sending the request to the first byte of the answer — mostly your API doing its work. Connection times (TCP, TLS) are the network and this computer."},{group:"Reading results",term:"Result",tech:"verdict",text:"The app's plain summary of a run: looks healthy, usable with warnings, or failing. It explains each part underneath."},{group:"Reading results",term:"Reference run",tech:"baseline",text:"A run you choose to compare later runs of the same API against, to see if they got faster or slower. Pick one in a report or in History."},{group:"Setting up a test",term:"Simulated users",tech:"virtual users · VUs",text:"Pretend users. Each one sends a request, waits for the answer, maybe pauses, and sends the next. A slow API gets fewer requests."},{group:"Setting up a test",term:"Request rate",tech:"arrival rate",text:"Instead of users, hold a fixed number of requests per second whatever the API does. The honest way to find how much an API can take."},{group:"Setting up a test",term:"Presets",text:"Smoke: tiny, just checks it works. Average: a normal day. Stress: more than usual. Spike: a sudden burst. Soak: a long run that finds slow leaks."},{group:"Setting up a test",term:"Ramp up / step by step",tech:"stages",text:"Change the load over time — for example, go up to 50 users over a minute, stay there, then go down."},{group:"Setting up a test",term:"Pause between requests",tech:"think time",text:"How long each simulated user waits before sending the next request, like a person reading the page."},{group:"Setting up a test",term:"Checks",text:"Your rules for a correct answer, like “status is 200” or “has a name field”. A fast answer with an error inside fails a good check."},{group:"Setting up a test",term:"Goals",tech:"thresholds",text:"Pass/fail limits for the whole test, like “95% of requests within 500 ms” and “fewer than 1% failed”."},{group:"Setting up a test",term:"Environment",tech:"{{variables}}",text:"A named set of values such as a base URL or a token. Write {{name}} in a request and switch environments (Dev, UAT) without editing it."},{group:"Setting up a test",term:"Run first",tech:"request chaining",text:"Send another saved request first — usually signing in — and use values from its answer, like a token, in this request."},{group:"Setting up a test",term:"Test data",tech:"CSV",text:"A spreadsheet file whose columns become {{variables}}. Each request uses the next row, so a test can use many users or IDs."},{group:"Setting up a test",term:"Auth",tech:"authentication",text:"How the request proves who it is: a Bearer token, a username and password (Basic), or an API key."},{group:"About the app",term:"k6",text:"The open-source load-testing engine the app runs on this computer for load tests."},{group:"About the app",term:"Practice API",text:"A small pretend shop built into the app — products, sign-in, orders, a slow and a flaky endpoint — so you can learn without testing a real system."},{group:"About the app",term:"Where results are kept",text:"On this computer only, as plain files in your app-data folder. History shows them and lets you delete them."}]],89142);var t=e.i(61666),s=e.i(83067),a=e.i(65296);let n="atc:tour",r=[{target:"#request-url",title:"1. Where the request goes",body:"Type or paste a URL here — or a whole curl command copied from your browser. {{name}} takes a value from the chosen environment."},{target:"section[aria-label=Request] [role=tablist]",title:"2. What to send",body:"Add parameters, headers, sign-in (Auth), and a body. Checks are your rules for a correct answer; Run first and Test data feed in values."},{target:"[data-tour=send]",title:"3. Try it once",body:"Send one request and see the answer on the right. Always do this first, so you know it works before testing it under load."},{target:"[data-tour=run]",title:"4. Test it under load",body:"Run load test sends many requests at once with simulated users. Choose how many in the Load tab, and pass/fail limits in Goals."},{target:"section[aria-label=Results]",title:"5. Read the result",body:"Answers and load reports appear here. Every report is saved on this computer, and you can rearrange its charts with Customize."},{target:"a[href='/history']",title:"6. Look back",body:"History keeps every run. Mark one as your reference run to see whether later runs got faster or slower."},{target:"[data-tour=help]",title:"Any word unclear?",body:"Help explains every term in plain language, and can start this tour again."}];e.s(["Tour",0,function(){let[e,l]=(0,s.useState)(null),[i,o]=(0,s.useState)(null),c=(0,s.useRef)(null),d=(0,s.useRef)(null),u=(0,s.useCallback)(e=>{let t=document.querySelector(r[e].target);return t&&t.getBoundingClientRect().width>0?t:null},[]),h=(0,s.useCallback)((e,t)=>{for(let s=e;s>=0&&s<r.length;s+=t)if(u(s))return l(s);l(null)},[u]);if((0,s.useEffect)(()=>{let e=()=>h(0,1);return window.addEventListener(n,e),()=>window.removeEventListener(n,e)},[h]),(0,s.useLayoutEffect)(()=>{if(null===e)return;let t=()=>{let t=u(e);if(!t)return;t.scrollIntoView({block:"nearest",inline:"nearest"});let s=t.getBoundingClientRect();o({top:s.top-6,left:s.left-6,width:s.width+12,height:Math.min(s.height+12,window.innerHeight-24)})};return t(),window.addEventListener("resize",t),window.addEventListener("scroll",t,!0),()=>{window.removeEventListener("resize",t),window.removeEventListener("scroll",t,!0)}},[e,u]),(0,s.useEffect)(()=>{if(null===e)return;d.current?.focus();let t=t=>{"Escape"===t.key&&l(null),"ArrowRight"===t.key&&h(e+1,1),"ArrowLeft"===t.key&&e>0&&h(e-1,-1)};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e,h]),null===e||!i||"u"<typeof document)return null;let m=r[e],p=!r.slice(e+1).some((t,s)=>u(e+1+s)),x=i.top+i.height+180<window.innerHeight?i.top+i.height+10:Math.max(12,i.top-10-(c.current?.offsetHeight??170)),f=Math.min(Math.max(12,i.left),window.innerWidth-320-12);return(0,a.createPortal)((0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{"aria-hidden":!0,className:"pointer-events-none fixed z-[80] rounded-lg ring-2 ring-accent transition-all duration-200",style:{...i,boxShadow:"0 0 0 9999px rgb(0 0 0 / 0.55)"}}),(0,t.jsxs)("div",{ref:c,role:"dialog","aria-modal":"false","aria-labelledby":"tour-title",className:"fixed z-[81] rounded-lg border border-line bg-panel p-4 shadow-2xl",style:{top:x,left:f,width:320},children:[(0,t.jsx)("h2",{id:"tour-title",className:"text-sm font-medium text-ink",children:m.title}),(0,t.jsx)("p",{className:"mt-1.5 text-sm text-mute",children:m.body}),(0,t.jsxs)("div",{className:"mt-4 flex items-center gap-2",children:[(0,t.jsxs)("span",{className:"text-xs text-mute",children:[e+1," of ",r.length]}),(0,t.jsx)("button",{type:"button",onClick:()=>l(null),className:"ml-auto rounded-md px-2 py-1 text-xs text-mute hover:text-ink",children:"Skip tour"}),e>0?(0,t.jsx)("button",{type:"button",onClick:()=>h(e-1,-1),className:"rounded-md border border-line px-2.5 py-1 text-xs text-ink hover:border-accent",children:"Back"}):null,(0,t.jsx)("button",{ref:d,type:"button",onClick:()=>p?l(null):h(e+1,1),className:"btn btn-primary px-3 py-1 text-xs",children:p?"Done":"Next"})]})]})]}),document.body)},"startTour",0,function(){window.dispatchEvent(new Event(n))}],5831)},7641,45672,51554,e=>{"use strict";var t=e.i(61666),s=e.i(8055),a=e.i(88293),n=e.i(87283),r=e.i(46443),l=e.i(83067),i=e.i(89142),o=e.i(5831),c=e.i(19286),d=e.i(50962);let u="apitestcenter-welcome",h="atc:welcome";function m(e){try{e?localStorage.setItem(u,"hidden"):localStorage.removeItem(u)}catch{}window.dispatchEvent(new Event(h))}function p({icon:e,title:s,text:a,onClick:n,disabled:r}){return(0,t.jsxs)("button",{type:"button",onClick:n,disabled:r,className:"flex flex-col items-start gap-1.5 rounded-lg border border-line bg-panel-2 px-4 py-3 text-left hover:border-accent disabled:opacity-50 disabled:hover:border-line",children:[(0,t.jsxs)("span",{className:"flex items-center gap-2 text-sm font-medium text-ink",children:[(0,t.jsx)("span",{className:"text-accent",children:e}),s]}),(0,t.jsx)("span",{className:"text-xs text-mute",children:a})]})}e.s(["WELCOME_EVENT",0,h,"WelcomeCard",0,function({practiceReady:e,onSimple:a,onSignIn:r,onHide:l}){return(0,t.jsxs)("div",{className:"relative flex flex-1 flex-col justify-center rounded-lg border border-line bg-panel px-6 py-8",children:[(0,t.jsx)("button",{type:"button",onClick:l,className:"absolute top-3 right-3 rounded p-1 text-mute hover:text-ink","aria-label":"Hide the getting-started guide",title:"Hide (bring it back from Help)",children:(0,t.jsx)(n.X,{size:15})}),(0,t.jsx)("h2",{className:"text-lg font-medium text-ink",children:"New here? Start with something safe to test"}),(0,t.jsx)("p",{className:"mt-1 max-w-xl text-sm text-mute",children:"The app has a small practice shop API built in. Nothing leaves this computer, so you can send requests and run load tests without worrying about a real system."}),(0,t.jsxs)("div",{className:"mt-5 grid gap-3",children:[(0,t.jsx)(p,{icon:(0,t.jsx)(d.Send,{size:16,"aria-hidden":!0}),title:"Try a simple request",text:"Fill in a request for the product list, with a check that the answer is right. Then press Send.",disabled:!e,onClick:a}),(0,t.jsx)(p,{icon:(0,t.jsx)(c.KeyRound,{size:16,"aria-hidden":!0}),title:"Try a sign-in example",text:"Adds two requests to Saved requests → Practice: Sign in, and My orders, which signs in first and uses the token.",disabled:!e,onClick:r}),(0,t.jsx)(p,{icon:(0,t.jsx)(s.Compass,{size:16,"aria-hidden":!0}),title:"Take the 1-minute tour",text:"See where to type, how to try a request once, then test it under load.",onClick:o.startTour})]}),e?null:(0,t.jsx)("p",{className:"mt-3 text-xs text-warn",children:"The practice API starts with the engine — it is offline right now."}),(0,t.jsx)("p",{className:"mt-5 text-xs text-mute",children:"Have your own API? Paste its URL — or a curl command from your browser's DevTools — into the bar above."})]})},"setWelcomeHidden",0,m,"welcomeHidden",0,function(){try{return"hidden"===localStorage.getItem(u)}catch{return!1}}],45672);var x=e.i(78739);let f=(0,e.i(99522).default)("chart-column",[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]),b=()=>fetch("/engine/settings/usage",{cache:"no-store"}).then(e=>e.ok?e.json():null),g=e=>fetch("/engine/settings/usage",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({enabled:e})}).then(e=>e.json());function v(){let[e,s]=(0,l.useState)(null),[a,n]=(0,l.useState)(!1);return((0,l.useEffect)(()=>{b().then(s).catch(()=>void 0)},[]),e)?(0,t.jsxs)("section",{className:"space-y-2 rounded-lg border border-line px-3 py-2.5",children:[(0,t.jsxs)("label",{className:"flex items-center justify-between gap-3 text-sm text-ink",children:[(0,t.jsxs)("span",{children:["Share anonymous usage counts",(0,t.jsx)("span",{className:"block text-xs text-mute",children:e.available?"Once a day: counts, app version, OS. Never URLs or results.":"Only the desktop app can send these; this window never does."})]}),(0,t.jsx)("input",{type:"checkbox",disabled:!e.available,checked:!0===e.enabled,onChange:e=>void g(e.target.checked).then(s),className:"h-4 w-4 accent-[var(--accent)]"})]}),(0,t.jsxs)("button",{type:"button",className:"text-xs text-accent hover:underline",onClick:()=>n(e=>!e),children:[a?"Hide":"Show"," exactly what would be sent"]}),a?(0,t.jsx)("pre",{className:"max-h-40 overflow-auto rounded-md bg-panel-2 p-2 font-mono text-[11px] text-mute",children:JSON.stringify(e.next,null,2)}):null]}):null}e.s(["UsageConsent",0,function(){let[e,s]=(0,l.useState)(null),[a,i]=(0,l.useState)(!1),[o,c]=(0,l.useState)(!1),d=(0,r.usePathname)();async function u(t){i(!1),s(await g(t).catch(()=>e))}return((0,l.useEffect)(()=>{let e=!1;return b().then(t=>{!e&&t&&(s(t),i(t.available&&null===t.enabled&&t.used))}).catch(()=>void 0),()=>{e=!0}},[d]),a&&e)?(0,t.jsxs)("aside",{role:"dialog","aria-labelledby":"usage-title",className:"fixed right-4 bottom-4 z-[60] w-[min(380px,calc(100vw-2rem))] rounded-xl border border-line bg-panel p-4 shadow-2xl",children:[(0,t.jsx)("button",{type:"button",onClick:()=>void u(!1),className:"absolute top-3 right-3 rounded p-1 text-mute hover:text-ink","aria-label":"No thanks",children:(0,t.jsx)(n.X,{size:14})}),(0,t.jsxs)("h2",{id:"usage-title",className:"flex items-center gap-2 pr-6 text-sm font-medium text-ink",children:[(0,t.jsx)(f,{size:16,className:"text-accent","aria-hidden":!0})," Help improve APITestCenter?"]}),(0,t.jsxs)("p",{className:"mt-2 text-sm text-mute",children:["Share ",(0,t.jsx)("span",{className:"text-ink",children:"anonymous counts"})," once a day — how many requests and load tests you ran, the app version, and your operating system. ",(0,t.jsx)("span",{className:"text-ink",children:"Never"})," URLs, results, or anything you type."]}),o?(0,t.jsx)("pre",{className:"mt-2 max-h-40 overflow-auto rounded-md bg-panel-2 p-2 font-mono text-[11px] text-mute",children:JSON.stringify(e.next,null,2)}):(0,t.jsx)("button",{type:"button",onClick:()=>c(!0),className:"mt-1 text-xs text-accent hover:underline",children:"See exactly what would be sent"}),(0,t.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,t.jsx)("button",{type:"button",onClick:()=>void u(!0),className:"btn btn-primary py-1.5 text-xs",children:"Yes, share counts"}),(0,t.jsx)("button",{type:"button",onClick:()=>void u(!1),className:"rounded-md px-3 py-1.5 text-xs text-mute hover:text-ink",children:"No thanks"})]}),(0,t.jsx)("p",{className:"mt-2 text-[11px] text-mute",children:"You can change this any time in Help."})]}):null},"UsageSetting",0,v],51554);let y="atc:help";e.s(["HelpPanel",0,function(){let[e,c]=(0,l.useState)(!1),[d,u]=(0,l.useState)(""),h=(0,l.useRef)(null),p=(0,l.useRef)(null),f=(0,r.usePathname)(),b=(0,r.useRouter)();function g(){c(!1),p.current?.focus()}(0,l.useEffect)(()=>{let e=()=>{p.current=document.activeElement,c(!0)};return window.addEventListener(y,e),()=>window.removeEventListener(y,e)},[]),(0,l.useEffect)(()=>{if(!e)return;window.setTimeout(()=>h.current?.focus(),0);let t=e=>"Escape"===e.key&&g();return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e]);let w=(0,l.useMemo)(()=>{let e=d.trim().toLowerCase(),t=i.GLOSSARY.filter(t=>!e||`${t.term} ${t.tech??""} ${t.text}`.toLowerCase().includes(e)),s=new Map;for(let e of t)s.set(e.group,[...s.get(e.group)??[],e]);return[...s]},[d]);return e?(0,t.jsxs)("div",{className:"fixed inset-0 z-[75] flex justify-end",children:[(0,t.jsx)("button",{type:"button","aria-label":"Close help",className:"absolute inset-0 bg-black/40",onClick:g}),(0,t.jsxs)("aside",{role:"dialog","aria-modal":"true","aria-labelledby":"help-title",className:"relative flex h-full w-full max-w-md flex-col border-l border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-center gap-2 border-b border-line px-5 py-4",children:[(0,t.jsx)("h2",{id:"help-title",className:"text-base font-medium text-ink",children:"Help"}),(0,t.jsx)("button",{type:"button",onClick:g,"aria-label":"Close",className:"ml-auto rounded p-1 text-mute hover:text-ink",children:(0,t.jsx)(n.X,{size:16})})]}),(0,t.jsxs)("div",{className:"space-y-3 border-b border-line px-5 py-4",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>{c(!1),"/"!==f&&b.push("/"),window.setTimeout(o.startTour,"/"===f?50:900)},className:"flex w-full items-center gap-3 rounded-lg border border-line px-3 py-2.5 text-left hover:border-accent",children:[(0,t.jsx)(s.Compass,{size:18,className:"text-accent","aria-hidden":!0}),(0,t.jsxs)("span",{children:[(0,t.jsx)("span",{className:"block text-sm text-ink",children:"Take the 1-minute tour"}),(0,t.jsx)("span",{className:"block text-xs text-mute",children:"Where to type, how to test once, then under load"})]})]}),(0,t.jsx)("button",{type:"button",onClick:()=>{m(!1),c(!1),"/"!==f&&b.push("/")},className:"text-xs text-accent hover:underline",children:"Show the getting-started guide on Test API again"}),(0,t.jsx)(v,{}),(0,t.jsx)("button",{type:"button",onClick:()=>{c(!1),(0,x.openAbout)()},className:"text-left text-xs text-accent hover:underline",children:"About APITestCenter — version, updates, your files"}),(0,t.jsx)("a",{href:"https://apitestcenter.com/docs/",target:"_blank",rel:"noreferrer",className:"block text-xs text-accent hover:underline",children:"User guide — every feature explained, at apitestcenter.com/docs"}),(0,t.jsxs)("label",{className:"relative block",children:[(0,t.jsx)("span",{className:"sr-only",children:"Search words"}),(0,t.jsx)(a.Search,{size:14,className:"pointer-events-none absolute top-1/2 left-2.5 -translate-y-1/2 text-mute","aria-hidden":!0}),(0,t.jsx)("input",{ref:h,value:d,onChange:e=>u(e.target.value),placeholder:"What does … mean?",className:"input py-1.5 pl-8"})]})]}),(0,t.jsxs)("div",{className:"min-h-0 flex-1 overflow-y-auto px-5 py-4",children:[0===w.length?(0,t.jsxs)("p",{className:"text-sm text-mute",children:["No word matches “",d,"”."]}):null,w.map(([e,s])=>(0,t.jsxs)("section",{className:"mb-6",children:[(0,t.jsx)("h3",{className:"mb-2 text-xs font-medium tracking-wide text-mute uppercase",children:e}),(0,t.jsx)("dl",{className:"space-y-3",children:s.map(e=>(0,t.jsxs)("div",{children:[(0,t.jsxs)("dt",{className:"text-sm font-medium text-ink",children:[e.term,e.tech?(0,t.jsx)("span",{className:"ml-2 text-xs font-normal text-mute",children:e.tech}):null]}),(0,t.jsx)("dd",{className:"mt-0.5 text-sm text-mute",children:e.text})]},e.term))})]},e))]})]})]}):null},"openHelp",0,function(){window.dispatchEvent(new Event(y))}],7641)},41997,36e3,42674,18043,28202,13318,e=>{"use strict";e.s(["AuthFields",()=>y,"authModeLabel",()=>j],41997);var t=e.i(61666);e.i(24856);var s=e.i(59100),a=e.i(59674),n=e.i(78451),r=e.i(19286),l=e.i(27813),i=e.i(63966),o=e.i(458),c=e.i(96659),d=e.i(83067),u=e.i(87283);function h({rows:e,onChange:s,keyPlaceholder:a,valuePlaceholder:n,noun:r,secretValues:l=!1}){let i=[...e,{key:"",value:""}];function o(e,t){let a=i.map((s,a)=>a===e?{...s,...t}:s);s(a.filter((e,t)=>t<a.length-1||e.key||e.value))}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)_2rem] bg-panel-2 text-xs text-mute",children:[(0,t.jsx)("span",{className:"px-2.5 py-1.5",children:a}),(0,t.jsx)("span",{className:"border-l border-line px-2.5 py-1.5",children:n}),(0,t.jsx)("span",{})]}),i.map((a,n)=>{let c=n===i.length-1;return(0,t.jsxs)("div",{className:"group grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_2rem] border-t border-line",children:[(0,t.jsx)("input",{value:a.key,"aria-label":`${r} ${n+1} name`,placeholder:c?`Add ${r}`:"",onChange:e=>o(n,{key:e.target.value}),className:"min-w-0 bg-transparent px-2.5 py-1.5 font-mono text-[13px] text-ink outline-none placeholder:text-mute focus:bg-panel-2"}),(0,t.jsx)("input",{value:a.value,type:l?"password":"text","aria-label":`${r} ${n+1} value`,onChange:e=>o(n,{value:e.target.value}),className:"min-w-0 border-l border-line bg-transparent px-2.5 py-1.5 font-mono text-[13px] text-ink outline-none focus:bg-panel-2"}),c?(0,t.jsx)("span",{}):(0,t.jsx)("button",{type:"button","aria-label":`Remove ${r} ${a.key||n+1}`,onClick:()=>s(e.filter((e,t)=>t!==n)),className:"grid place-items-center text-mute opacity-60 group-hover:opacity-100 hover:text-bad focus:opacity-100",children:(0,t.jsx)(u.X,{size:14})})]},n)})]})}e.s(["KeyValueEditor",0,h],36e3);var m=e.i(31753),p=e.i(28867),x=e.i(5305);e.s([],42674);var f=e.i(6278);async function b(e,t){let s=await fetch(`/engine${e}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)}),a=await s.json().catch(()=>null);if(!s.ok)throw Error(a?.error??`Engine error (${s.status})`);return a}function g({value:e,onChange:s,defaults:a={}}){let{vars:u}=(0,f.useWorkspace)(),v=t=>s({...e,...t}),[y,w]=(0,d.useState)(null),[j,k]=(0,d.useState)(null),[N,C]=(0,d.useState)(null),[S,E]=(0,d.useState)(!1),T=(0,d.useRef)(null),A=(0,d.useCallback)(()=>{let{value:t,missing:s}=(0,n.substituteDeep)(e,{...a,...u});if(s.length)throw Error(`${s.map(e=>`{{${e}}}`).join(", ")} ${1===s.length?"isn't":"aren't"} defined — pick an environment`);return(0,x.oauthWire)(t)},[e,a,u]),L=(0,d.useCallback)(async()=>{try{let e=A();w(await b("/oauth/status",{oauth:e})),C(null)}catch(e){w(null),C(e instanceof Error?e.message:String(e))}},[A]);async function P(){k("token");try{w(await b("/oauth/token",{oauth:A()})),C(null)}catch(e){C(e instanceof Error?e.message:String(e))}finally{k(null)}}async function I(){k("browser");try{let e=A(),{id:t,url:s}=await b("/oauth/authorize",{oauth:e});window.open(s,"_blank","noopener"),E(!0),C(null);let a=Date.now();T.current&&window.clearInterval(T.current),T.current=window.setInterval(async()=>{let e=await fetch(`/engine/oauth/authorize/${t}`).then(e=>e.json()).catch(()=>({status:"unknown"}));"waiting"===e.status&&Date.now()-a<33e4||(window.clearInterval(T.current),T.current=null,E(!1),"done"===e.status?await L():C(e.error??"The sign-in ended without a token — try again"))},1500)}catch(e){C(e instanceof Error?e.message:String(e))}finally{k(null)}}async function R(){try{w(await b("/oauth/clear",{oauth:A()}))}catch(e){C(e instanceof Error?e.message:String(e))}}(0,d.useEffect)(()=>{let e=window.setTimeout(()=>void L(),400);return()=>window.clearTimeout(e)},[L]),(0,d.useEffect)(()=>()=>void(T.current&&window.clearInterval(T.current)),[]);let q="authorization_code"===e.grant;return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Grant type"}),(0,t.jsx)(p.Segmented,{label:"Grant type",value:e.grant,onChange:e=>v({grant:e}),options:[{value:"client_credentials",label:"Client credentials"},{value:"password",label:"Password"},{value:"authorization_code",label:"Authorization code"}]}),(0,t.jsx)("p",{className:"mt-1 text-xs text-mute",children:"client_credentials"===e.grant?"Service to service: the app signs in as itself. Best for load tests.":"password"===e.grant?"Signs in as a user with a username and password (older APIs and test accounts).":"Signs in as a user in the browser, once; the token is then kept and refreshed."})]}),q?(0,t.jsx)(m.LabeledInput,{label:"Authorization URL",mono:!0,value:e.authUrl,placeholder:"https://auth.example.com/oauth/authorize",onChange:e=>v({authUrl:e})}):null,(0,t.jsx)(m.LabeledInput,{label:"Token URL",mono:!0,value:e.tokenUrl,placeholder:"https://auth.example.com/oauth/token",onChange:e=>v({tokenUrl:e})}),(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsx)(m.LabeledInput,{label:"Client ID",mono:!0,value:e.clientId,onChange:e=>v({clientId:e})}),(0,t.jsx)(m.LabeledInput,{label:q?"Client secret (if it has one)":"Client secret",secret:!0,mono:!0,value:e.clientSecret,placeholder:"or {{clientSecret}}",onChange:e=>v({clientSecret:e})})]}),"password"===e.grant?(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsx)(m.LabeledInput,{label:"Username",value:e.username,onChange:e=>v({username:e})}),(0,t.jsx)(m.LabeledInput,{label:"Password",secret:!0,value:e.password,onChange:e=>v({password:e})})]}):null,(0,t.jsx)(m.LabeledInput,{label:"Scope",mono:!0,value:e.scope,placeholder:"orders:read orders:write",onChange:e=>v({scope:e}),hint:"Space-separated. Leave empty for the server's default."}),q?(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-end",children:[(0,t.jsx)(m.LabeledInput,{label:"Redirect URL",mono:!0,value:e.redirectUri,onChange:e=>v({redirectUri:e}),hint:"Add exactly this address to your OAuth app. It must be on this computer (127.0.0.1 or localhost)."}),(0,t.jsxs)("label",{className:"mb-6 flex items-center gap-2 text-sm text-ink",children:[(0,t.jsx)("input",{type:"checkbox",checked:e.pkce,onChange:e=>v({pkce:e.target.checked}),className:"accent-[var(--accent)]"}),"PKCE"]})]}):null,(0,t.jsxs)("details",{className:"rounded-md border border-line",children:[(0,t.jsx)("summary",{className:"cursor-pointer px-3 py-2 text-sm text-mute hover:text-ink",children:"More: client authentication, extra fields"}),(0,t.jsxs)("div",{className:"space-y-3 border-t border-line p-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Send the client ID and secret"}),(0,t.jsx)(p.Segmented,{label:"Client authentication",value:e.clientAuth,onChange:e=>v({clientAuth:e}),options:[{value:"basic",label:"In a Basic auth header"},{value:"body",label:"In the request body"}]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Extra fields for the token request (and the sign-in page), e.g. audience or resource"}),(0,t.jsx)(h,{rows:e.extra,onChange:e=>v({extra:e}),keyPlaceholder:"audience",valuePlaceholder:"https://api.example.com",noun:"field"})]})]})]}),(0,t.jsxs)("div",{className:"rounded-md border border-line bg-panel-2/50 px-3 py-2.5",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)(r.KeyRound,{size:14,className:y?.hasToken?"text-ok":"text-mute","aria-hidden":!0}),S?(0,t.jsx)("span",{className:"text-ink",children:"Waiting for you to sign in in the browser…"}):y?.hasToken?(0,t.jsxs)("span",{className:"text-ink",children:["Token ready ",(0,t.jsxs)("span",{className:"text-mute",children:["· ",function(e){if(null===e)return"no expiry given";let t=Math.round((e-Date.now())/6e4);return t<=0?"expired — a new one is fetched on the next request":t<90?`expires in ${t} min`:`expires in ${Math.round(t/60)} h`}(y.expiresAt),y.scope?` \xb7 ${y.scope}`:""]})]}):(0,t.jsx)("span",{className:"text-mute",children:q?"Not signed in yet.":"No token yet — one is fetched on the first Send or load test."}),(0,t.jsxs)("span",{className:"ml-auto flex gap-1.5",children:[q?(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1 text-xs",disabled:null!==j||S,onClick:()=>void I(),children:["browser"===j?(0,t.jsx)(l.Loader2,{size:13,className:"animate-spin"}):(0,t.jsx)(i.LogIn,{size:13}),y?.hasToken?"Sign in again":"Sign in in the browser"]}):(0,t.jsxs)("button",{type:"button",className:"btn btn-secondary py-1 text-xs",disabled:null!==j,onClick:()=>void P(),children:["token"===j?(0,t.jsx)(l.Loader2,{size:13,className:"animate-spin"}):(0,t.jsx)(o.RefreshCw,{size:13}),"Get new token"]}),y?.hasToken?(0,t.jsx)("button",{type:"button",className:"rounded p-1 text-mute hover:text-bad",title:"Forget this token","aria-label":"Forget this token",onClick:()=>void R(),children:(0,t.jsx)(c.Trash2,{size:13})}):null]})]}),N?(0,t.jsx)("p",{className:"mt-1.5 text-xs text-bad",children:N}):null,(0,t.jsxs)("p",{className:"mt-1.5 text-xs text-mute",children:["Requests go out with ",(0,t.jsx)("code",{className:"font-mono",children:"Authorization: Bearer …"}),". The token is kept encrypted on this computer and renewed before it runs out — in load tests too."]})]})]})}var v=e.i(80707);function y({value:e,onChange:n,inheritLabel:r="Inherit",inheritNote:l,secretNote:i,defaults:o}){let c=e.authMode;return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("label",{className:"flex flex-wrap items-center gap-2 text-xs text-mute",children:["Auth type",(0,t.jsx)(v.Select,{label:"Auth type",value:c,onChange:e=>n({authMode:e}),minWidth:300,options:[{value:"inherit",label:r,hint:"Use the auth set on the folder above"},{value:"none",label:"None",hint:"No credentials"},{value:"bearer",label:"Bearer token",hint:"Authorization: Bearer …"},{value:"basic",label:"Basic",hint:"Username and password, in every request"},{value:"api_key",label:"API key",hint:"A key in a header or the query"},{value:"oauth2",label:"OAuth 2.0",hint:"Get a token from a sign-in server, renewed by itself"},{value:"digest",label:"Digest",hint:"Username and password, answered to the server's challenge"},{value:"ntlm",label:"NTLM",hint:"Windows sign-in (IIS, SharePoint, internal APIs)"},{value:"aws_sigv4",label:"AWS Signature",hint:"Sign every request with an AWS key (API Gateway, S3, Lambda URLs)"},{value:"jwt",label:"JWT (signed here)",hint:"The app signs a JSON Web Token with your secret or private key"}],className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-sm text-ink hover:border-mute focus-visible:border-accent focus-visible:outline-none"})]}),"oauth2"===c?(0,t.jsx)(g,{value:e.oauth,onChange:e=>n({oauth:e}),defaults:o}):null,"jwt"===c?(0,t.jsx)(a.JwtFields,{value:e.jwt,onChange:e=>n({jwt:e})}):null,"aws_sigv4"===c?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsx)(m.LabeledInput,{label:"Access key ID",mono:!0,value:e.aws.accessKeyId,placeholder:"AKIA… or {{awsAccessKeyId}}",onChange:t=>n({aws:{...e.aws,accessKeyId:t}})}),(0,t.jsx)(m.LabeledInput,{label:"Secret access key",secret:!0,mono:!0,value:e.aws.secretAccessKey,placeholder:"or {{awsSecretAccessKey}}",onChange:t=>n({aws:{...e.aws,secretAccessKey:t}})}),(0,t.jsx)(m.LabeledInput,{label:"Region",mono:!0,value:e.aws.region,placeholder:"eu-west-1",onChange:t=>n({aws:{...e.aws,region:t}})}),(0,t.jsx)(m.LabeledInput,{label:"Service",mono:!0,value:e.aws.service,placeholder:"execute-api",onChange:t=>n({aws:{...e.aws,service:t}}),hint:"execute-api (API Gateway), s3, lambda (function URLs), es…"})]}),(0,t.jsx)(m.LabeledInput,{label:"Session token (temporary credentials only)",secret:!0,mono:!0,value:e.aws.sessionToken,placeholder:"or {{awsSessionToken}}",onChange:t=>n({aws:{...e.aws,sessionToken:t}})}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"Every request is signed just before it goes out — in load tests too, one fresh signature per request. The secret key and token are kept encrypted on this computer."})]}):null,"inherit"===c?(0,t.jsx)("div",{className:"text-sm text-mute",children:l}):null,"none"===c?(0,t.jsx)("p",{className:"text-sm text-mute",children:"No credentials are sent."}):null,"bearer"===c?(0,t.jsx)(m.LabeledInput,{label:"Token",secret:!0,mono:!0,value:e.token,placeholder:"eyJhbGciOi… or {{token}}",onChange:e=>n({token:(0,s.normalizeBearerToken)(e)}),hint:'Paste with or without the "Bearer " prefix.'}):null,"basic"===c||"digest"===c?(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsx)(m.LabeledInput,{label:"Username",value:e.username,onChange:e=>n({username:e})}),(0,t.jsx)(m.LabeledInput,{label:"Password",secret:!0,value:e.password,onChange:e=>n({password:e})})]}):null,"digest"===c?(0,t.jsx)("p",{className:"text-xs text-mute",children:"The server answers the first request with a challenge (401); the app answers it without sending the password. MD5 and SHA-256, with or without -sess."}):null,"ntlm"===c?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-3",children:[(0,t.jsx)(m.LabeledInput,{label:"Username",value:e.username,placeholder:"ann or CORP\\ann",onChange:e=>n({username:e})}),(0,t.jsx)(m.LabeledInput,{label:"Password",secret:!0,value:e.password,onChange:e=>n({password:e})}),(0,t.jsx)(m.LabeledInput,{label:"Domain",value:e.domain,placeholder:"CORP",onChange:e=>n({domain:e})})]}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"NTLMv2. The sign-in takes a short exchange with the server on one connection; in load tests those extra 401 replies are not counted as requests."})]}):null,"api_key"===c?(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-[minmax(0,1fr)_minmax(0,2fr)_auto]",children:[(0,t.jsx)(m.LabeledInput,{label:"Name",mono:!0,value:e.apiName,onChange:e=>n({apiName:e})}),(0,t.jsx)(m.LabeledInput,{label:"Value",secret:!0,mono:!0,value:e.apiValue,onChange:e=>n({apiValue:e})}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Send in"}),(0,t.jsx)(p.Segmented,{label:"Send API key in",value:e.apiIn,onChange:e=>n({apiIn:e}),options:[{value:"header",label:"Header"},{value:"query",label:"Query"}]})]})]}):null,"none"!==c&&"inherit"!==c&&"oauth2"!==c&&"aws_sigv4"!==c&&"jwt"!==c&&i?(0,t.jsx)("p",{className:"text-xs text-mute",children:i}):null]})}let w={bearer:"Bearer token",basic:"Basic sign-in",api_key:"API key",oauth2:"OAuth 2.0 sign-in",digest:"Digest sign-in",ntlm:"NTLM sign-in",aws_sigv4:"AWS signature",jwt:"signed JWT"};function j(e){return"inherit"===e?"inherited":"none"===e?"no auth":w[e]}var k=e.i(99112),N=e.i(67938),C=e.i(71189);let S=[{value:"json",label:"JSON field",placeholder:"data.access_token",hint:"Path in the JSON answer, like data.items[0].id"},{value:"header",label:"Header",placeholder:"X-Request-Id",hint:"A response header name"},{value:"body",label:"Text pattern",placeholder:"token=(\\w+)",hint:"A regular expression; the part in ( ) is kept"}];function E({rules:e,onChange:s,results:a,showUnused:n}){let r=(t,a)=>s(e.map((e,s)=>s===t?{...e,...a}:e));return(0,t.jsx)("ul",{className:"space-y-2",children:e.map((l,i)=>{let o=S.find(e=>e.value===l.from),c=a.get(l.name);return(0,t.jsxs)("li",{className:"flex flex-wrap items-center gap-2 rounded-md border border-line bg-panel px-2.5 py-2",children:[(0,t.jsx)("span",{className:"text-xs text-mute",children:"Save"}),(0,t.jsx)("select",{value:l.from,onChange:e=>r(i,{from:e.target.value}),className:"input w-auto py-1","aria-label":"Where the value is",children:S.map(e=>(0,t.jsx)("option",{value:e.value,children:e.label},e.value))}),(0,t.jsx)("input",{value:l.path,onChange:e=>r(i,{path:e.target.value}),placeholder:o.placeholder,title:o.hint,"aria-label":o.hint,className:"input min-w-40 flex-1 py-1 font-mono text-xs"}),(0,t.jsx)("span",{className:"text-xs text-mute",children:"as"}),(0,t.jsxs)("span",{className:"inline-flex items-center font-mono text-xs text-mute",children:["{{",(0,t.jsx)("input",{value:l.name,onChange:e=>r(i,{name:e.target.value.replace(/[^\w.-]/g,"")}),"aria-label":"Variable name",className:"input mx-0.5 w-28 py-1 font-mono text-xs"}),"}}"]}),(0,t.jsxs)("span",{className:"ml-auto flex items-center gap-2",children:[c?c.found?(0,t.jsxs)("span",{className:"text-xs text-ok",title:"Found on the last Send",children:["✓ ",c.preview]}):(0,t.jsx)("span",{className:"text-xs text-bad",title:"Not found on the last Send",children:"✕ not found"}):n&&!n.has(l.name)&&l.name?(0,t.jsx)("span",{className:"text-xs text-warn",children:"not used yet"}):null,(0,t.jsx)("button",{type:"button",onClick:()=>s(e.filter((e,t)=>t!==i)),className:"rounded p-1 text-mute hover:text-bad","aria-label":`Remove {{${l.name}}}`,children:(0,t.jsx)(u.X,{size:14})})]})]},i)})})}function T(e){let t=[e.url,e.bodyText,e.token,e.username,e.password,e.apiName,e.apiValue,...e.params.flatMap(e=>[e.key,e.value]),...e.headers.map(e=>e.value)].join("\n");return new Set((0,n.findVariables)(t))}function A({name:e,used:s}){return(0,t.jsx)("code",{className:`rounded px-1.5 py-0.5 font-mono text-xs ${!1===s?"bg-warn/10 text-warn":"bg-accent-dim text-accent"}`,title:!1===s?"Not used in this request yet":void 0,children:`{{${e}}}`})}let L=[{value:"sequential",label:"In order",title:"Request 1 uses row 1, request 2 uses row 2… then starts again"},{value:"random",label:"Random",title:"Each request picks a random row"},{value:"per-user",label:"One row per user",title:"Each simulated user keeps its own row — good for logins"}];e.s(["RunFirstPanel",0,function({draft:e,onChange:s,currentId:a,result:n}){let{index:r}=(0,f.useWorkspace)(),l=(r?.requests??[]).filter(e=>e.id!==a),i=e.before,o=T(e),c=t=>s({...e,before:t}),d=i?.extract??[],u=new Map((n?.values??[]).map(e=>[e.name,e]));return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("p",{className:"text-sm text-mute",children:["Send another saved request first — like signing in — and use values from its answer here. A sign-in token becomes"," ",(0,t.jsx)(A,{name:"token"}),", which you can put in Auth, a header, the URL, or the body."]}),(0,t.jsxs)("label",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)("span",{className:"text-ink",children:"First, send"}),(0,t.jsxs)("select",{value:i?.requestId??"",onChange:e=>(e=>{if(!e)return c(null);let t=l.find(t=>t.id===e);t&&c({requestId:t.id,requestName:t.name,extract:d.length?d:[{name:"token",from:"json",path:""}]})})(e.target.value),className:"input w-auto min-w-56 py-1","aria-label":"Saved request to send first",children:[(0,t.jsx)("option",{value:"",children:"Nothing — send this request on its own"}),l.map(e=>(0,t.jsxs)("option",{value:e.id,children:[e.collection?`${e.collection} / `:"",e.name," · ",e.method]},e.id))]}),i&&!l.some(e=>e.id===i.requestId)?(0,t.jsxs)("span",{className:"text-xs text-bad",children:["“",i.requestName,"” is no longer saved — pick another"]}):null]}),l.length?null:(0,t.jsxs)("p",{className:"rounded-md border border-dashed border-line px-3 py-2 text-xs text-mute",children:["No other saved requests yet. Open your sign-in request, press ",(0,t.jsx)("kbd",{className:"kbd",children:"Ctrl"})," + ",(0,t.jsx)("kbd",{className:"kbd",children:"S"})," to save it, then pick it here."]}),i?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)("h4",{className:"text-xs font-medium text-mute",children:"Values to take from its answer"}),(0,t.jsx)(E,{rules:d,onChange:e=>c({...i,extract:e}),results:u,showUnused:o}),(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>c({...i,extract:[...d,{name:`value${d.length+1}`,from:"json",path:""}]}),className:"inline-flex items-center gap-1 rounded-md border border-line px-2.5 py-1 text-xs text-ink hover:border-accent",children:[(0,t.jsx)(C.Plus,{size:13,"aria-hidden":!0})," Add a value"]}),d.some(e=>"token"===e.name)&&"none"===e.authMode?(0,t.jsxs)("button",{type:"button",onClick:()=>s({...e,authMode:"bearer",token:"{{token}}"}),className:"inline-flex items-center gap-1 rounded-md border border-accent/40 px-2.5 py-1 text-xs text-accent hover:bg-accent-dim",children:["Use ","{{token}}"," as the Bearer token"]}):null]}),n&&!n.ok&&n.error?(0,t.jsx)("p",{className:"text-xs text-bad",children:n.error}):null,(0,t.jsx)("p",{className:"text-xs text-mute",children:"Send runs it every time. A load test runs it once before starting, and every request uses the same values."})]}):null]})},"SaveValuesPanel",0,function({draft:e,onChange:s,results:a}){let n=e.saveValues,r=t=>s({...e,saveValues:t}),l=new Map((a??[]).map(e=>[e.name,e]));return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("p",{className:"text-sm text-mute",children:["Take values from this answer for the requests after it — like the id of a new order, used by “Get order” as ",(0,t.jsx)(A,{name:"orderId"}),"."]}),n.length?(0,t.jsx)(E,{rules:n,onChange:r,results:l}):null,(0,t.jsxs)("button",{type:"button",onClick:()=>r([...n,{name:n.length?`value${n.length+1}`:"id",from:"json",path:n.length?"":"id"}]),className:"inline-flex items-center gap-1 rounded-md border border-line px-2.5 py-1 text-xs text-ink hover:border-accent",children:[(0,t.jsx)(C.Plus,{size:13,"aria-hidden":!0})," Add a value"]}),(0,t.jsxs)("ul",{className:"list-disc space-y-1 pl-5 text-xs text-mute",children:[(0,t.jsxs)("li",{children:["In ",(0,t.jsx)("span",{className:"text-ink",children:"Run collection"}),", every request after this one can use them. Put this request first in the run order."]}),(0,t.jsx)("li",{children:"After a Send, they stay until you close the app, so the next request you send can use them too."}),(0,t.jsx)("li",{children:"A load test does not save values; it uses the ones saved by your last Send."})]})]})},"TestDataPanel",0,function({draft:e,onChange:s}){let a=(0,d.useRef)(null),[n,r]=(0,d.useState)([]),[l,i]=(0,d.useState)(null),o=e.testData,c=T(e),u=t=>s({...e,testData:t});async function h(t){if(i(null),r([]),t.size>5242880)return i(`${t.name} is ${(t.size/1024/1024).toFixed(1)} MB — the limit is 5 MB`);let s=(0,k.parseCsv)(await t.text());if(!s.columns.length)return i(`${t.name} is empty`);if(!s.rows.length)return i(`${t.name} has a header row but no data rows`);if(s.rows.length>1e5)return i(`${t.name} has ${s.rows.length.toLocaleString()} rows — the limit is 100,000`);let a=s.columns.find(t=>e.before?.extract.some(e=>e.name===t));if(a)return i(`The column “${a}” has the same name as a Run-first value — rename one of them`);r(s.problems),u({fileName:t.name,columns:s.columns,rows:s.rows,order:o?.order??"sequential"})}return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("p",{className:"text-sm text-mute",children:["Test with many users, IDs, or search terms. Each column in a CSV file becomes a variable such as ",(0,t.jsx)(A,{name:"email"}),", and each request uses the next row."]}),(0,t.jsx)("input",{ref:a,type:"file",accept:".csv,text/csv,text/plain",className:"sr-only","aria-label":"Choose a CSV file",onChange:e=>{let t=e.target.files?.[0];e.target.value="",t&&h(t)}}),o?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)("span",{className:"font-medium text-ink",children:o.fileName}),(0,t.jsxs)("span",{className:"text-mute",children:["· ",o.rows.length.toLocaleString()," rows"]}),(0,t.jsxs)("span",{className:"ml-auto flex gap-2",children:[(0,t.jsx)("button",{type:"button",onClick:()=>a.current?.click(),className:"rounded-md border border-line px-2.5 py-1 text-xs text-ink hover:border-accent",children:"Replace"}),(0,t.jsx)("button",{type:"button",onClick:()=>u(null),className:"rounded-md border border-line px-2.5 py-1 text-xs text-ink hover:border-bad hover:text-bad",children:"Remove"})]})]}),(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-1.5 text-xs text-mute",children:["Variables:",o.columns.map(e=>(0,t.jsx)(A,{name:e,used:c.has(e)},e))]}),o.columns.some(e=>!c.has(e))?(0,t.jsx)("p",{className:"text-xs text-warn",children:"Highlighted columns are not used in this request yet — type them into the URL, params, headers, or body."}):null,(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)("span",{className:"text-mute",children:"Which row each request uses"}),(0,t.jsx)(p.Segmented,{label:"Row order",value:o.order,options:L,onChange:e=>u({...o,order:e})})]}),(0,t.jsx)("div",{className:"overflow-x-auto rounded-md border border-line",children:(0,t.jsxs)("table",{className:"w-full text-left font-mono text-xs",children:[(0,t.jsxs)("caption",{className:"sr-only",children:["First rows of ",o.fileName]}),(0,t.jsx)("thead",{className:"bg-panel-2 text-mute",children:(0,t.jsxs)("tr",{children:[(0,t.jsx)("th",{scope:"col",className:"px-2 py-1 font-normal",children:"#"}),o.columns.map(e=>(0,t.jsx)("th",{scope:"col",className:"px-2 py-1 font-normal",children:e},e))]})}),(0,t.jsx)("tbody",{children:o.rows.slice(0,5).map((e,s)=>(0,t.jsxs)("tr",{className:"border-t border-line",children:[(0,t.jsx)("td",{className:"px-2 py-1 text-mute",children:s+1}),e.map((e,s)=>(0,t.jsx)("td",{className:"max-w-48 truncate px-2 py-1 text-ink",title:e,children:e},s))]},s))})]})}),o.rows.length>5?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Showing 5 of ",o.rows.length.toLocaleString()," rows. Send uses row 1."]}):(0,t.jsx)("p",{className:"text-xs text-mute",children:"Send uses row 1."})]}):(0,t.jsxs)("button",{type:"button",onClick:()=>a.current?.click(),onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();let t=e.dataTransfer.files[0];t&&h(t)},className:"flex w-full flex-col items-center gap-1 rounded-lg border border-dashed border-line px-4 py-6 text-sm text-mute hover:border-accent hover:text-ink",children:[(0,t.jsx)(N.FileUp,{size:18,"aria-hidden":!0}),(0,t.jsx)("span",{className:"text-ink",children:"Choose a CSV file"}),(0,t.jsx)("span",{className:"text-xs",children:"or drop it here · first row is the column names · up to 5 MB"})]}),l?(0,t.jsx)("p",{className:"text-xs text-bad",children:l}):null,n.length?(0,t.jsx)("ul",{className:"list-disc space-y-0.5 pl-5 text-xs text-warn",children:n.map(e=>(0,t.jsx)("li",{children:e},e))}):null]})}],18043);var P=e.i(70632);let I=[{label:"Status",make:()=>({type:"status",expect:"2xx"})},{label:"JSON field",make:()=>({type:"json",path:"",op:"exists",value:""})},{label:"Body text",make:()=>({type:"body",op:"contains",value:""})},{label:"Header",make:()=>({type:"header",name:"content-type",op:"contains",value:"json"})},{label:"Response time",make:()=>({type:"time",maxMs:1e3})}],R={status:"Status",json:"JSON",body:"Body",header:"Header",time:"Time"},q="rounded-md border border-line bg-panel-2 px-2 py-1 text-[13px] text-ink outline-none focus:border-accent";function $({check:e,onChange:s}){switch(e.type){case"status":return(0,t.jsxs)("label",{className:"flex items-center gap-2 text-xs text-mute",children:["is",(0,t.jsx)("input",{"aria-label":"Expected status",value:e.expect,onChange:t=>s({...e,expect:t.target.value}),placeholder:"2xx",className:`${q} w-32 font-mono`})]});case"time":return(0,t.jsxs)("label",{className:"flex items-center gap-2 text-xs text-mute",children:["within",(0,t.jsx)("input",{"aria-label":"Maximum response time in ms",type:"number",min:1,value:e.maxMs,onChange:t=>s({...e,maxMs:Math.max(1,Number(t.target.value)||1)}),className:`${q} w-24 font-mono`}),"ms"]});case"body":return(0,t.jsxs)("span",{className:"flex min-w-0 flex-1 items-center gap-2",children:[(0,t.jsxs)("select",{"aria-label":"Body condition",value:e.op,onChange:t=>s({...e,op:t.target.value}),className:q,children:[(0,t.jsx)("option",{value:"contains",children:"contains"}),(0,t.jsx)("option",{value:"not_contains",children:"does not contain"})]}),(0,t.jsx)("input",{"aria-label":"Text",value:e.value,onChange:t=>s({...e,value:t.target.value}),placeholder:'"status":"ok"',className:`${q} min-w-0 flex-1 font-mono`})]});case"json":return(0,t.jsxs)("span",{className:"flex min-w-0 flex-1 flex-wrap items-center gap-2",children:[(0,t.jsx)("input",{"aria-label":"JSON path",value:e.path,onChange:t=>s({...e,path:t.target.value}),placeholder:"data.id",className:`${q} w-40 font-mono`}),(0,t.jsxs)("select",{"aria-label":"JSON condition",value:e.op,onChange:t=>s({...e,op:t.target.value}),className:q,children:[(0,t.jsx)("option",{value:"exists",children:"exists"}),(0,t.jsx)("option",{value:"equals",children:"equals"}),(0,t.jsx)("option",{value:"not_equals",children:"does not equal"}),(0,t.jsx)("option",{value:"contains",children:"contains"})]}),"exists"!==e.op?(0,t.jsx)("input",{"aria-label":"Expected value",value:e.value,onChange:t=>s({...e,value:t.target.value}),placeholder:"ok",className:`${q} min-w-0 flex-1 font-mono`}):null]});case"header":return(0,t.jsxs)("span",{className:"flex min-w-0 flex-1 flex-wrap items-center gap-2",children:[(0,t.jsx)("input",{"aria-label":"Header name",value:e.name,onChange:t=>s({...e,name:t.target.value}),placeholder:"content-type",className:`${q} w-36 font-mono`}),(0,t.jsxs)("select",{"aria-label":"Header condition",value:e.op,onChange:t=>s({...e,op:t.target.value}),className:q,children:[(0,t.jsx)("option",{value:"exists",children:"exists"}),(0,t.jsx)("option",{value:"equals",children:"equals"}),(0,t.jsx)("option",{value:"contains",children:"contains"})]}),"exists"!==e.op?(0,t.jsx)("input",{"aria-label":"Expected value",value:e.value,onChange:t=>s({...e,value:t.target.value}),className:`${q} min-w-0 flex-1 font-mono`}):null]})}}e.s(["ChecksEditor",0,function({checks:e,onChange:s,results:a}){let n=new Map((a??[]).map(e=>[e.name,e.ok]));return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("p",{className:"text-sm text-mute",children:["Checks decide whether a response is ",(0,t.jsx)("em",{children:"correct"}),", not just fast. A 200 with an error message inside fails a good check."]}),e.length>0?(0,t.jsx)("ul",{className:"space-y-2",children:e.map((a,r)=>{let l=n.get((0,P.checkLabel)(a));return(0,t.jsxs)("li",{className:"flex flex-wrap items-center gap-2 rounded-md border border-line bg-panel px-2.5 py-2",children:[(0,t.jsx)("span",{className:"w-14 shrink-0 text-xs font-medium text-mute",children:R[a.type]}),(0,t.jsx)($,{check:a,onChange:t=>s(e.map((e,s)=>s===r?t:e))}),(0,t.jsxs)("span",{className:"ml-auto flex items-center gap-2",children:[void 0===l?null:l?(0,t.jsx)("span",{className:"text-xs text-ok",title:"Passed on the last Send",children:"✓ pass"}):(0,t.jsx)("span",{className:"text-xs text-bad",title:"Failed on the last Send",children:"✕ fail"}),(0,t.jsx)("button",{type:"button","aria-label":`Remove check: ${(0,P.checkLabel)(a)}`,onClick:()=>s(e.filter((e,t)=>t!==r)),className:"rounded p-1 text-mute hover:text-bad",children:(0,t.jsx)(u.X,{size:14})})]})]},r)})}):(0,t.jsx)("p",{className:"rounded-md border border-dashed border-line px-3 py-3 text-sm text-mute",children:"No checks yet. Without checks, a load test only counts HTTP errors (4xx, 5xx, timeouts)."}),(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-1.5",children:[(0,t.jsx)("span",{className:"text-xs text-mute",children:"Add"}),I.map(a=>(0,t.jsxs)("button",{type:"button",disabled:e.length>=20,onClick:()=>s([...e,a.make()]),className:"inline-flex items-center gap-1 rounded-md border border-line px-2 py-1 text-xs text-ink hover:border-accent disabled:opacity-40",children:[(0,t.jsx)(C.Plus,{size:12,"aria-hidden":!0}),a.label]},a.label))]}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["JSON paths look like ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"data.items[0].id"}),". Status accepts"," ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"2xx"}),", ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"200,201"}),", or"," ",(0,t.jsx)("code",{className:"font-mono text-ink",children:"200-299"}),"."]})]})}],28202),e.s(["Tabs",0,function({id:e,items:s,value:a,onChange:n,label:r,trailing:l,className:i=""}){let o=(0,d.useRef)([]);return(0,t.jsxs)("div",{className:`flex items-end gap-2 border-b border-line ${i}`,children:[(0,t.jsx)("div",{role:"tablist","aria-label":r,className:"-mb-px flex min-w-0 flex-1 flex-wrap gap-x-1",children:s.map((r,l)=>{let i=r.id===a;return(0,t.jsxs)("button",{ref:e=>{o.current[l]=e},id:`${e}-tab-${r.id}`,type:"button",role:"tab","aria-selected":i,"aria-controls":`${e}-panel-${r.id}`,tabIndex:i?0:-1,onClick:()=>n(r.id),onKeyDown:e=>{let t;return t=-1,void("ArrowRight"===e.key&&(t=(l+1)%s.length),"ArrowLeft"===e.key&&(t=(l-1+s.length)%s.length),"Home"===e.key&&(t=0),"End"===e.key&&(t=s.length-1),!(t<0)&&(e.preventDefault(),n(s[t].id),o.current[t]?.focus()))},className:`flex shrink-0 items-center gap-1.5 border-b-2 px-2 py-2 text-sm transition-colors ${i?"border-accent text-ink":"border-transparent text-mute hover:text-ink"}`,children:[r.label,null!=r.badge&&!1!==r.badge?(0,t.jsx)("span",{className:"rounded bg-panel-2 px-1.5 font-mono text-xs text-mute",children:r.badge}):null]},r.id)})}),l?(0,t.jsx)("div",{className:"flex shrink-0 items-center gap-2 pb-1.5",children:l}):null]})},"tabPanelProps",0,function(e,t){return{role:"tabpanel",id:`${e}-panel-${t}`,"aria-labelledby":`${e}-tab-${t}`}}],13318)},59674,80707,e=>{"use strict";e.s(["JwtFields",()=>d],59674);var t=e.i(61666),s=e.i(67938),a=e.i(31753),n=e.i(1675),r=e.i(95486),l=e.i(60961),i=e.i(83067),o=e.i(65296);function c({value:e,options:s,groups:a=[],onChange:d,onOpen:u,label:h,className:m="",buttonContent:p,minWidth:x=180,disabled:f=!1}){let[b,g]=(0,i.useState)(!1),[v,y]=(0,i.useState)(0),[w,j]=(0,i.useState)(new Set),[k,N]=(0,i.useState)(null),C=(0,i.useRef)(null),S=(0,i.useRef)(null),E=(0,i.useId)(),T=s.find(t=>t.value===e),A=[],L=new Set;s.forEach((e,t)=>{let s=e.group?a.find(t=>t.id===e.group):void 0;s&&!L.has(s.id)&&(L.add(s.id),A.push({kind:"group",group:s})),(!s||w.has(s.id))&&A.push({kind:"option",index:t})}),(0,i.useLayoutEffect)(()=>{if(!b)return;let e=()=>{let e=C.current?.getBoundingClientRect();if(!e)return;let t=Math.max(e.width,x),s=S.current?.offsetHeight??260,a=window.innerHeight-e.bottom-8,n=e.top-8,r=a<Math.min(s,200)&&n>a;N({left:Math.min(Math.max(8,e.left),window.innerWidth-t-8),top:r?Math.max(8,e.top-Math.min(s,n)-4):e.bottom+4,width:t,maxHeight:Math.max(140,(r?n:a)-4)})};return e(),window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[b,x,A.length]),(0,i.useEffect)(()=>{if(!b)return;let e=e=>{let t=e.target;S.current?.contains(t)||C.current?.contains(t)||g(!1)},t=e=>{S.current?.contains(e.target)||g(!1)};return document.addEventListener("pointerdown",e,!0),document.addEventListener("scroll",t,!0),()=>{document.removeEventListener("pointerdown",e,!0),document.removeEventListener("scroll",t,!0)}},[b]),(0,i.useEffect)(()=>{b&&S.current?.querySelector(`[data-index="${v}"]`)?.scrollIntoView({block:"nearest"})},[b,v]);let P=()=>{let t=new Set(a.filter(e=>e.defaultOpen).map(e=>e.id));T?.group&&t.add(T.group),j(t);let n=0,r=0,l=new Set;for(let i of s){let s=i.group&&a.some(e=>e.id===i.group)?i.group:void 0;s&&!l.has(s)&&(l.add(s),r++),(!s||t.has(s))&&(i.value===e&&(n=r),r++)}y(n),g(!0),u?.()},I=(e,t)=>j(s=>{let a=new Set(s);return t??!a.has(e.id)?a.add(e.id):a.delete(e.id),a}),R=e=>{let t=A[e];if(!t)return;if("group"===t.kind)return I(t.group);let a=s[t.index];a&&d(a.value),g(!1),C.current?.focus()},q=e=>{if("group"===e.kind)return e.group.text.toLowerCase();let t=s[e.index];return(t.text??("string"==typeof t.label?t.label:String(t.value))).toLowerCase()};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("button",{ref:C,type:"button",disabled:f,role:"combobox","aria-label":h,"aria-haspopup":"listbox","aria-expanded":b,"aria-controls":b?E:void 0,"aria-activedescendant":b?`${E}-${v}`:void 0,onClick:()=>b?g(!1):P(),onKeyDown:function(e){if(f)return;if(!b){["ArrowDown","ArrowUp","Enter"," "].includes(e.key)&&(e.preventDefault(),P());return}let t=A[v];if("Escape"===e.key||"Tab"===e.key)"Escape"===e.key&&e.preventDefault(),g(!1);else if("ArrowDown"===e.key)e.preventDefault(),y(e=>Math.min(A.length-1,e+1));else if("ArrowUp"===e.key)e.preventDefault(),y(e=>Math.max(0,e-1));else if("Home"===e.key||"End"===e.key)e.preventDefault(),y("Home"===e.key?0:A.length-1);else if("ArrowRight"===e.key&&t?.kind==="group")e.preventDefault(),I(t.group,!0);else if("ArrowLeft"===e.key&&t){e.preventDefault();let a="group"===t.kind?t.group.id:s[t.index].group,n=A.findIndex(e=>"group"===e.kind&&e.group.id===a);if(n<0)return;y(n),I(A[n].group,!1)}else if("Enter"===e.key||" "===e.key)e.preventDefault(),R(v);else if(1===e.key.length){let t=e.key.toLowerCase(),s=A.findIndex((e,s)=>s>v&&q(e).startsWith(t)),a=s>=0?s:A.findIndex(e=>q(e).startsWith(t));a>=0&&y(a)}},className:`inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap disabled:opacity-50 ${m}`,children:[(0,t.jsx)("span",{className:"min-w-0 truncate",children:p??T?.label}),(0,t.jsx)(r.ChevronDown,{size:14,"aria-hidden":!0,className:`shrink-0 text-mute transition-transform ${b?"rotate-180":""}`})]}),b&&"u">typeof document?(0,o.createPortal)((0,t.jsx)("ul",{ref:S,id:E,role:"listbox","aria-label":h,style:{top:k?.top??-9999,left:k?.left??-9999,minWidth:k?.width,maxHeight:k?.maxHeight},className:"fixed z-[80] max-w-[min(32rem,calc(100vw-16px))] overflow-auto rounded-lg border border-line bg-panel p-1 shadow-2xl",children:A.map((a,r)=>{if("group"===a.kind){let e=a.group,s=w.has(e.id);return(0,t.jsxs)("li",{id:`${E}-${r}`,"data-index":r,role:"option","aria-selected":!1,"aria-expanded":s,onPointerEnter:()=>y(r),onPointerDown:e=>e.preventDefault(),onClick:()=>I(e),className:`flex cursor-pointer items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-medium text-mute ${r===v?"bg-panel-2":""} ${r>0?"mt-0.5":""}`,children:[(0,t.jsx)(l.ChevronRight,{size:14,"aria-hidden":!0,className:`shrink-0 transition-transform ${s?"rotate-90":""}`}),(0,t.jsx)("span",{className:"min-w-0 truncate text-ink",children:e.label}),e.hint?(0,t.jsx)("span",{className:"shrink-0 font-normal",children:e.hint}):null,e.action?(0,t.jsx)("button",{type:"button",title:e.action.title,onClick:t=>{t.stopPropagation(),g(!1),e.action.onClick()},className:"ml-auto shrink-0 rounded px-1 font-normal text-accent hover:underline",children:e.action.label}):null]},`g:${e.id}`)}let i=s[a.index];return(0,t.jsxs)("li",{id:`${E}-${r}`,"data-index":r,role:"option","aria-selected":i.value===e,onPointerEnter:()=>y(r),onPointerDown:e=>e.preventDefault(),onClick:()=>R(r),className:`flex cursor-pointer items-start gap-2 rounded-md py-1.5 pr-2.5 text-sm ${i.group?"pl-6":"pl-2.5"} ${r===v?"bg-panel-2":""} ${i.className??"text-ink"}`,children:[(0,t.jsx)(n.Check,{size:14,"aria-hidden":!0,className:`mt-0.5 shrink-0 ${i.value===e?"text-accent":"invisible"}`}),i.inline?(0,t.jsxs)("span",{className:"flex min-w-0 flex-1 items-baseline gap-4",children:[(0,t.jsx)("span",{className:"shrink-0",children:i.label}),i.hint?(0,t.jsx)("span",{className:"ml-auto min-w-0 truncate text-xs text-mute",children:i.hint}):null]}):(0,t.jsxs)("span",{className:"min-w-0",children:[(0,t.jsx)("span",{className:"block truncate",children:i.label}),i.hint?(0,t.jsx)("span",{className:"block truncate text-xs text-mute",children:i.hint}):null]})]},i.value)})}),document.body):null]})}function d({value:e,onChange:n}){let r=t=>n({...e,...t}),l=e.algorithm.startsWith("HS"),i=function(e){try{let t=JSON.parse(e||"{}");return t&&"object"==typeof t&&!Array.isArray(t)?null:"The claims must be a JSON object"}catch(e){return e instanceof Error?e.message:"Not valid JSON"}}(e.payload);return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-[auto_minmax(0,1fr)] sm:items-end",children:[(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-mute",children:["Algorithm",(0,t.jsx)(c,{label:"JWT algorithm",value:e.algorithm,onChange:e=>r({algorithm:e}),minWidth:260,options:[{value:"HS256",label:"HS256",hint:"HMAC with a shared secret"},{value:"HS384",label:"HS384",hint:"HMAC with a shared secret"},{value:"HS512",label:"HS512",hint:"HMAC with a shared secret"},{value:"RS256",label:"RS256",hint:"RSA private key"},{value:"RS384",label:"RS384",hint:"RSA private key"},{value:"RS512",label:"RS512",hint:"RSA private key"},{value:"PS256",label:"PS256",hint:"RSA-PSS private key"},{value:"ES256",label:"ES256",hint:"EC private key (P-256)"},{value:"ES384",label:"ES384",hint:"EC private key (P-384)"},{value:"ES512",label:"ES512",hint:"EC private key (P-521)"}],className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 font-mono text-sm text-ink"})]}),l?(0,t.jsx)(a.LabeledInput,{label:"Secret",secret:!0,mono:!0,value:e.secret,placeholder:"or {{jwtSecret}}",onChange:e=>r({secret:e})}):(0,t.jsx)("div",{className:"text-xs text-mute",children:"The private key (PEM) below signs the token; the API checks it with the public key."})]}),l?null:(0,t.jsxs)("label",{className:"block",children:[(0,t.jsxs)("span",{className:"mb-1 flex items-center justify-between text-xs text-mute",children:["Private key (PEM)",(0,t.jsxs)("span",{className:"relative inline-flex cursor-pointer items-center gap-1 text-accent hover:underline",children:[(0,t.jsx)(s.FileUp,{size:12,"aria-hidden":!0})," Load a .pem file",(0,t.jsx)("input",{type:"file",accept:".pem,.key",className:"absolute inset-0 cursor-pointer opacity-0",onChange:e=>{let t=e.target.files?.[0];t&&t.text().then(e=>r({privateKey:e})),e.target.value=""}})]})]}),(0,t.jsx)("textarea",{value:e.privateKey,onChange:e=>r({privateKey:e.target.value}),rows:4,spellCheck:!1,placeholder:"-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----",className:"input font-mono text-xs"})]}),(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Claims (JSON) — iat and exp are added unless you set them"}),(0,t.jsx)("textarea",{value:e.payload,onChange:e=>r({payload:e.target.value}),rows:5,spellCheck:!1,className:`input font-mono text-[13px] ${i?"border-bad":""}`}),(0,t.jsx)("span",{className:`mt-1 block text-xs ${i?"text-bad":"text-mute"}`,children:i??'For example { "sub": "user-1", "aud": "orders-api", "scope": "read" }. {{variables}} work here.'})]}),(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1.5fr)_minmax(0,1fr)]",children:[(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Valid for (minutes)"}),(0,t.jsx)("input",{type:"number",min:1,value:Math.max(1,Math.round(e.lifetimeSec/60)),onChange:e=>r({lifetimeSec:Math.max(60,60*Math.round(Number(e.target.value)||1))}),className:"input font-mono"})]}),(0,t.jsx)(a.LabeledInput,{label:"Key ID (kid)",mono:!0,value:e.kid,placeholder:"optional",onChange:e=>r({kid:e})}),(0,t.jsx)(a.LabeledInput,{label:"Header",mono:!0,value:e.headerName,onChange:e=>r({headerName:e})}),(0,t.jsx)(a.LabeledInput,{label:"Prefix",mono:!0,value:e.prefix,placeholder:"none",onChange:e=>r({prefix:e})})]}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"A fresh token is signed for every Send. In load tests the app signs the tokens before the test starts and switches to the next before one expires — the key itself never goes to the load generator. The secret and key are kept encrypted on this computer."})]})}e.s(["Select",0,c],80707)},31753,65238,e=>{"use strict";e.s(["LabeledInput",()=>C,"RequestEditor",()=>y],31753);var t=e.i(61666);e.i(24856);var s=e.i(78451),a=e.i(43514),n=e.i(83067),r=e.i(22543),l=e.i(41997),i=e.i(18043),o=e.i(28202),c=e.i(36e3),d=e.i(28867),u=e.i(13318),h=e.i(56931);e.i(42674);var m=e.i(5305),p=e.i(6278);async function x(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error??`Engine error (${e.status})`);return t}let f=(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)}),b={get:e=>fetch(`/engine/workspace/folders?path=${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>x(e)),chain:e=>e?fetch(`/engine/workspace/folders/chain?collection=${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>x(e)):Promise.resolve([]),save:(e,t)=>f("PUT","/engine/workspace/folders",{path:e,settings:t}).then(e=>x(e)),move:(e,t)=>f("POST","/engine/workspace/folders/move",{from:e,to:t}).then(e=>x(e)),remove:e=>f("DELETE",`/engine/workspace/folders?path=${encodeURIComponent(e)}`).then(e=>x(e))};async function g(e,t,s){let a=(0,m.applyFolders)(e,await b.chain(t??""));return{draft:a.draft,vars:{...a.vars,...s}}}function v(e){let{index:t}=(0,p.useWorkspace)(),[s,a]=(0,n.useState)([]);return(0,n.useEffect)(()=>{let t=!0;return b.chain(e??"").then(e=>t&&a(e)).catch(()=>t&&a([])),()=>{t=!1}},[e,t]),s}function y({id:e,draft:s,onChange:r,extraTabs:l=[],checkResults:c,currentId:d,setupResult:h,savedResults:p,collection:x}){var f,b;let[g,k]=(0,n.useState)("params"),N=(0,m.draftCounts)(s),C=v(x),S=(0,m.applyFolders)(s,C).inherited,E=e=>r({...s,...e}),T=[{id:"params",label:"Params",badge:N.params||void 0},{id:"headers",label:"Headers",badge:N.headers+S.headers.length||void 0},{id:"auth",label:N.auth||S.authFrom?(0,t.jsxs)("span",{title:S.authFrom?`Auth from folder ${S.authFrom}`:`Auth: ${w(s.authMode)}`,children:["Auth ",(0,t.jsx)("span",{className:"text-ok","aria-label":S.authFrom?"(from folder)":`(${w(s.authMode)})`,children:"●"})]}):"Auth"},...(0,m.hasBody)(s.method)?[{id:"body",label:"Body",badge:N.body?s.bodyMode:void 0}]:[],{id:"checks",label:"Checks",badge:function(e,s){if(!e)return;if(!s||0===s.length)return e;let a=s.filter(e=>e.ok).length;return(0,t.jsxs)("span",{className:a===s.length?"text-ok":"text-bad",title:`${a} of ${s.length} passed on the last Send`,children:[a,"/",s.length]})}(N.checks,c)},{id:"save",label:(0,t.jsx)("span",{title:"Take values from this answer, like an order id, for the requests after it",children:"Save values"}),badge:N.saveValues?function(e,s){if(!s?.length)return e;let a=s.filter(e=>e.found).length;return(0,t.jsxs)("span",{className:a===s.length?"text-ok":"text-bad",title:`${a} of ${s.length} found on the last Send`,children:[a,"/",s.length]})}(N.saveValues,p):void 0},{id:"before",label:(0,t.jsx)("span",{title:"Send a saved request first, like signing in, and use values from its answer",children:"Run first"}),badge:N.before?(f=h)?f.ok?(0,t.jsx)("span",{className:"text-ok",title:"Worked on the last Send",children:"✓"}):(0,t.jsx)("span",{className:"text-bad",title:f.error,children:"✕"}):"on":void 0},{id:"data",label:(0,t.jsx)("span",{title:"Use rows from a CSV file as variables",children:"Test data"}),badge:N.testData?(b=N.testData)>=1e3?`${Math.round(b/100)/10}k rows`:`${b} row${1===b?"":"s"}`:void 0},...l.map(e=>({id:e.id,label:e.label,badge:e.badge})),{id:"settings",label:(0,t.jsxs)("span",{className:"inline-flex items-center gap-1",title:"Timeout, redirects, connections, TLS",children:[(0,t.jsx)(a.Settings2,{size:14,"aria-hidden":!0}),"Settings"]})}],A=T.some(e=>e.id===g)?g:"params",L=l.find(e=>e.id===A);return(0,t.jsxs)("div",{children:[(0,t.jsx)(u.Tabs,{id:e,label:"Request settings",items:T,value:A,onChange:k}),(0,t.jsx)("div",{...(0,u.tabPanelProps)(e,A),className:"pt-4",children:L?L.content:"checks"===A?(0,t.jsx)(o.ChecksEditor,{checks:s.checks,onChange:e=>E({checks:e}),results:c}):"save"===A?(0,t.jsx)(i.SaveValuesPanel,{draft:s,onChange:r,results:p}):"before"===A?(0,t.jsx)(i.RunFirstPanel,{draft:s,onChange:r,currentId:d,result:h}):"data"===A?(0,t.jsx)(i.TestDataPanel,{draft:s,onChange:r}):(0,t.jsx)(j,{tab:A,draft:s,onChange:r,patch:E,chain:C,collection:x??null})})]})}function w(e){return"api_key"===e?"key":e}function j({tab:e,draft:s,onChange:a,patch:n,chain:r,collection:i}){if("params"===e)return(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsx)(c.KeyValueEditor,{rows:s.params,onChange:e=>a((0,m.withParts)(s,{params:e})),keyPlaceholder:"Query parameter",valuePlaceholder:"Value",noun:"parameter"}),(0,t.jsxs)("details",{className:"group rounded-md border border-line",children:[(0,t.jsx)("summary",{className:"cursor-pointer px-3 py-2 text-sm text-mute hover:text-ink",children:"Edit origin and path separately"}),(0,t.jsxs)("div",{className:"grid gap-3 border-t border-line p-3 sm:grid-cols-2",children:[(0,t.jsx)(C,{label:"Base URL",value:s.baseUrl,placeholder:"https://api.example.com",onChange:e=>a((0,m.withParts)(s,{baseUrl:e}))}),(0,t.jsx)(C,{label:"Path",value:s.endpoint,placeholder:"/v1/orders",onChange:e=>a((0,m.withParts)(s,{endpoint:e}))})]})]})]});if("headers"===e){let e=function(e,t){let s=new Set(e.headers.filter(e=>e.key.trim()).map(e=>e.key.trim().toLowerCase())),a=new Map;for(let e of t)for(let t of e.settings.headers)t.key.trim()&&a.set(t.key.trim().toLowerCase(),{key:t.key.trim(),value:t.value,from:e.path});return[...a.entries()].filter(([e])=>!s.has(e)).map(([,e])=>e)}(s,r);return(0,t.jsxs)("div",{className:"space-y-2",children:[e.length?(0,t.jsxs)("div",{className:"rounded-md border border-line bg-panel-2/50 px-3 py-2 text-xs",children:[(0,t.jsx)("p",{className:"mb-1 text-mute",children:"Also sent, from its folder — a header with the same name below replaces it:"}),(0,t.jsx)("ul",{className:"space-y-0.5 font-mono",children:e.map(e=>(0,t.jsxs)("li",{className:"flex flex-wrap gap-x-2",children:[(0,t.jsx)("span",{className:"text-ink",children:e.key}),(0,t.jsx)("span",{className:"min-w-0 truncate text-mute",children:e.value}),(0,t.jsxs)("span",{className:"font-sans text-mute",children:["· ",e.from]})]},e.key))})]}):null,(0,t.jsx)(c.KeyValueEditor,{rows:s.headers,onChange:e=>n({headers:e}),keyPlaceholder:"Header",valuePlaceholder:"Value",noun:"header"}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Credentials belong in ",(0,t.jsx)("span",{className:"text-ink",children:"Auth"})," — they are masked there and never exported."]})]})}if("auth"===e){let e=(0,m.applyFolders)(s,r).inherited.authFrom,a=e?r.find(t=>t.path===e):void 0;return(0,t.jsx)(l.AuthFields,{value:s,onChange:n,defaults:(0,m.applyFolders)(s,r).vars,inheritLabel:"From folder",inheritNote:a?(0,t.jsxs)(t.Fragment,{children:["Uses the ",(0,t.jsx)("span",{className:"text-ink",children:(0,l.authModeLabel)(a.settings.auth.authMode)})," set on the folder"," ",(0,t.jsx)("span",{className:"text-ink",children:a.path}),". Change it in that folder's settings (⋯ next to the folder)."]}):i?(0,t.jsx)(t.Fragment,{children:"No folder above this request sets auth, so no credentials are sent. Set it once on a folder (⋯ → Folder settings) and every request inside uses it."}):(0,t.jsx)(t.Fragment,{children:"This request isn't saved in a folder, so no credentials are sent. Save it in a folder that has auth, or pick a type here."}),secretNote:"Kept encrypted on this computer. Exports record the auth type, never the secret."})}return"body"===e?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,t.jsx)(d.Segmented,{label:"Body type",value:s.bodyMode,onChange:e=>n({bodyMode:e}),options:[{value:"none",label:"None"},{value:"json",label:"JSON"},{value:"text",label:"Text"}]}),"json"===s.bodyMode?(0,t.jsx)("button",{type:"button",className:"text-xs text-accent hover:underline",onClick:()=>n({bodyText:function(e){try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}(s.bodyText)}),children:"Format JSON"}):null]}),"none"!==s.bodyMode?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("textarea",{value:s.bodyText,"aria-label":"Request body",spellCheck:!1,onChange:e=>n({bodyText:e.target.value}),rows:12,className:"input font-mono text-[13px] leading-5",placeholder:"json"===s.bodyMode?'{\n "id": 1\n}':"raw body"}),"json"===s.bodyMode?(0,t.jsx)(N,{text:s.bodyText}):null]}):(0,t.jsx)("p",{className:"text-sm text-mute",children:"No body is sent."})]}):(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,t.jsx)(C,{label:"Timeout",mono:!0,value:s.timeout,error:(0,m.durationError)(s.timeout,!1),onChange:e=>n({timeout:e}),hint:"Per request, e.g. 30s or 2m."}),(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Max redirects"}),(0,t.jsx)("input",{type:"number",min:0,max:20,value:s.maxRedirects,onChange:e=>n({maxRedirects:Number(e.target.value)}),className:"input font-mono"})]}),(0,t.jsx)(S,{checked:s.connectionReuse,onChange:e=>n({connectionReuse:e}),label:"Reuse TCP connections",hint:"On mirrors a real client with keep-alive. Off makes every request pay DNS, TCP, and TLS again."}),(0,t.jsx)(S,{checked:s.tlsSkip,onChange:e=>n({tlsSkip:e}),label:"Skip TLS certificate check",hint:"Only for self-signed lab certificates. Never use it to hide a real certificate problem."}),(0,t.jsx)("div",{className:"sm:col-span-2",children:(0,t.jsx)(k,{url:s.url,defaults:(0,m.applyFolders)(s,r).vars})})]})}function k({url:e,defaults:a}){let{vars:r}=(0,p.useWorkspace)(),[l,i]=(0,n.useState)(null),[o,c]=(0,n.useState)(0),d=(0,s.substitute)(e,{...a,...r}).text,u=/^https:\/\//i.test(d);return(0,n.useEffect)(()=>{let e=()=>c(e=>e+1);return window.addEventListener(h.CERTIFICATES_CHANGED,e),()=>window.removeEventListener(h.CERTIFICATES_CHANGED,e)},[]),(0,n.useEffect)(()=>{if(!u)return i(null);let e=!0,t=window.setTimeout(()=>void h.certificateApi.match(d).then(t=>e&&i(t.host)),300);return()=>{e=!1,window.clearTimeout(t)}},[d,u,o]),(0,t.jsxs)("p",{className:"flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md border border-line px-3 py-2 text-sm",children:[(0,t.jsx)("span",{className:"text-mute",children:"Client certificate (mutual TLS):"}),(0,t.jsx)("span",{className:"text-ink",children:l?(0,t.jsxs)(t.Fragment,{children:["the one for ",(0,t.jsx)("span",{className:"font-mono",children:l})]}):u?"none for this host":"only for https addresses"}),(0,t.jsx)("button",{type:"button",className:"ml-auto text-xs text-accent hover:underline",onClick:h.openCertificates,children:"Manage certificates"})]})}function N({text:e}){if(!e.trim())return(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Empty body sends ","{}","."]});try{return JSON.parse(e),(0,t.jsx)("p",{className:"text-xs text-ok",children:"Valid JSON"})}catch(e){return(0,t.jsx)("p",{className:"text-xs text-bad",children:e instanceof Error?e.message:"Invalid JSON"})}}function C({label:e,value:s,onChange:a,placeholder:r,hint:l,secret:i=!1,mono:o=!1,type:c="text",error:d}){let[u,h]=(0,n.useState)(!1);return(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:e}),(0,t.jsxs)("span",{className:"relative block",children:[(0,t.jsx)("input",{type:i&&!u?"password":c,autoComplete:"off",spellCheck:!1,value:s,placeholder:r,"aria-invalid":!!d||void 0,onChange:e=>a(e.target.value),className:`input ${o?"font-mono":""} ${i?"pr-14":""} ${d?"border-bad":""}`}),i?(0,t.jsx)("button",{type:"button",onClick:e=>{e.preventDefault(),h(e=>!e)},className:"absolute inset-y-0 right-1 my-1 rounded px-2 text-xs text-mute hover:text-ink",children:u?"Hide":"Show"}):null]}),d?(0,t.jsx)("span",{className:"mt-1 block text-xs text-bad",children:d}):l?(0,t.jsx)("span",{className:"mt-1 block text-xs text-mute",children:l}):null]})}function S({checked:e,onChange:s,label:a,hint:n}){return(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:e,onChange:e=>s(e.target.checked),className:"mt-0.5 accent-[var(--accent)]"}),(0,t.jsxs)("span",{className:"flex items-center gap-1.5",children:[a,n?(0,t.jsx)(r.Hint,{text:n,label:`About ${a}`}):null]})]})}e.s(["folderApi",0,b,"useFolderChain",0,v,"useFolderVarNames",0,function(e){let{index:t}=(0,p.useWorkspace)(),s=[...new Set(e.filter(e=>!!e))].sort().join("\n"),[a,r]=(0,n.useState)(new Set);return(0,n.useEffect)(()=>{let e=!0;return Promise.all((s?s.split("\n"):[]).map(e=>b.chain(e).catch(()=>[]))).then(t=>{e&&r(new Set(t.flat().flatMap(e=>e.settings.variables.map(e=>e.key))))}),()=>{e=!1}},[s,t]),a},"withFolders",0,g],65238)},56931,e=>{"use strict";e.s(["CERTIFICATES_CHANGED",()=>m,"CertificatesDialog",()=>b,"certificateApi",()=>x,"openCertificates",()=>p]);var t=e.i(61666),s=e.i(67938),a=e.i(27813),n=e.i(30135),r=e.i(96659),l=e.i(87283),i=e.i(83067),o=e.i(31753),c=e.i(39170),d=e.i(28867),u=e.i(56396);let h="atc:certificates",m="atc:certificates-changed";function p(){window.dispatchEvent(new Event(h))}let x={list:()=>fetch("/engine/certificates",{cache:"no-store"}).then(e=>e.ok?e.json():[]),match:e=>fetch(`/engine/certificates/match?url=${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>e.ok?e.json():{host:null}).catch(()=>({host:null}))};async function f(e,t){if(!t)return{name:e.name,text:await e.text()};let s=new Uint8Array(await e.arrayBuffer()),a="";for(let e=0;e<s.length;e+=32768)a+=String.fromCharCode(...s.subarray(e,e+32768));return{name:e.name,base64:btoa(a)}}function b(){let e=(0,u.useToast)(),p=(0,c.useConfirm)(),[b,g]=(0,i.useState)(!1),[v,y]=(0,i.useState)([]),[w,j]=(0,i.useState)(""),[k,N]=(0,i.useState)("pem"),[C,S]=(0,i.useState)(null),[E,T]=(0,i.useState)(null),[A,L]=(0,i.useState)(null),[P,I]=(0,i.useState)(""),[R,q]=(0,i.useState)(!1),[$,M]=(0,i.useState)(null),D=(0,i.useRef)(null);async function z(){q(!0),M(null);try{let t=await fetch("/engine/certificates",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({host:w,kind:k,cert:C?.text,key:E?.text,pfx:A?.base64,passphrase:P||void 0})}),s=await t.json().catch(()=>null);if(!t.ok)throw Error(s?.error??"Could not save the certificate");e(`Requests to ${s?.host??w} now present this certificate`,"success"),j(""),S(null),T(null),L(null),I(""),M(null),y(await x.list()),window.dispatchEvent(new Event(m))}catch(e){M(e instanceof Error?e.message:String(e))}finally{q(!1)}}async function H(e){await p({title:`Remove the certificate for ${e.host}?`,body:"Requests to that host stop presenting it. Its private key is deleted from this computer.",confirmLabel:"Remove",tone:"danger"})&&(await fetch(`/engine/certificates/${encodeURIComponent(e.id)}`,{method:"DELETE"}).catch(()=>void 0),y(await x.list()),window.dispatchEvent(new Event(m)))}if((0,i.useEffect)(()=>{let e=()=>g(!0);return window.addEventListener(h,e),()=>window.removeEventListener(h,e)},[]),(0,i.useEffect)(()=>{b&&x.list().then(y)},[b]),!b)return null;let O=w.trim()&&("pfx"===k?A:C&&E),U=(e,a,n,r,l=!1)=>(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:e}),(0,t.jsxs)("span",{className:"flex items-center gap-2 rounded-md border border-dashed border-line px-3 py-2 text-sm hover:border-mute",children:[(0,t.jsx)(s.FileUp,{size:14,className:"text-mute","aria-hidden":!0}),(0,t.jsx)("span",{className:`min-w-0 truncate ${n?"text-ink":"text-mute"}`,children:n?.name??"Choose a file…"}),(0,t.jsx)("input",{type:"file",accept:a,className:"sr-only",onChange:e=>{let t=e.target.files?.[0];t&&f(t,l).then(r),e.target.value=""}})]})]});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&&g(!1),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-labelledby":"certs-title",onKeyDown:e=>"Escape"===e.key&&g(!1),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",{children:[(0,t.jsx)("h2",{id:"certs-title",className:"text-base font-medium text-ink",children:"Client certificates"}),(0,t.jsx)("p",{className:"text-xs text-mute",children:"For APIs that ask for a certificate (mutual TLS). Every request to the host presents it — on Send, in collection runs and in load tests."})]}),(0,t.jsx)("button",{type:"button","aria-label":"Close",className:"rounded p-1 text-mute hover:text-ink",onClick:()=>g(!1),children:(0,t.jsx)(l.X,{size:16})})]}),(0,t.jsxs)("div",{className:"min-h-0 flex-1 space-y-5 overflow-auto px-5 py-4",children:[v.length?(0,t.jsx)("ul",{className:"divide-y divide-line rounded-md border border-line",children:v.map(e=>{let s=!!e.expires&&Date.parse(e.expires)<Date.now();return(0,t.jsxs)("li",{className:"flex items-center gap-3 px-3 py-2 text-sm",children:[(0,t.jsx)(n.ShieldCheck,{size:15,className:s?"text-bad":"text-ok","aria-hidden":!0}),(0,t.jsxs)("span",{className:"min-w-0 flex-1",children:[(0,t.jsx)("span",{className:"block truncate font-mono text-ink",children:e.host}),(0,t.jsx)("span",{className:"block truncate text-xs text-mute",children:[e.subject?`CN ${e.subject}`:"","pfx"===e.kind?"PFX":"PEM",e.hasPassphrase?"passphrase saved":"",e.expires?`${s?"expired":"valid until"} ${new Date(e.expires).toLocaleDateString()}`:""].filter(Boolean).join(" · ")})]}),(0,t.jsx)("button",{type:"button","aria-label":`Remove the certificate for ${e.host}`,onClick:()=>void H(e),className:"rounded p-1 text-mute hover:text-bad",children:(0,t.jsx)(r.Trash2,{size:14})})]},e.id)})}):(0,t.jsx)("p",{className:"text-sm text-mute",children:"No certificates yet."}),(0,t.jsxs)("section",{className:"space-y-3 rounded-md border border-line p-4",children:[(0,t.jsx)("h3",{className:"text-sm font-medium text-ink",children:"Add a certificate"}),(0,t.jsxs)("label",{className:"block",children:[(0,t.jsx)("span",{className:"mb-1 block text-xs text-mute",children:"Host"}),(0,t.jsx)("input",{ref:D,value:w,onChange:e=>j(e.target.value),placeholder:"api.example.com",className:"input font-mono",spellCheck:!1}),(0,t.jsxs)("span",{className:"mt-1 block text-xs text-mute",children:[(0,t.jsx)("code",{className:"font-mono",children:"*.example.com"})," for every subdomain; add ",(0,t.jsx)("code",{className:"font-mono",children:":8443"})," for one port only."]})]}),(0,t.jsx)(d.Segmented,{label:"Certificate format",value:k,onChange:N,options:[{value:"pem",label:"Certificate + key (PEM, CRT)"},{value:"pfx",label:"PFX / P12"}]}),"pem"===k?(0,t.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[U("Certificate",".pem,.crt,.cer",C,S),U("Private key",".pem,.key",E,T)]}):U("PFX or P12 file",".pfx,.p12",A,L,!0),(0,t.jsx)(o.LabeledInput,{label:"Passphrase (if the key or file has one)",secret:!0,value:P,onChange:I}),$?(0,t.jsx)("p",{className:"text-sm text-bad",children:$}):null,(0,t.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,t.jsx)("p",{className:"text-xs text-mute",children:"Checked before saving. The private key and passphrase are kept encrypted on this computer and never exported."}),(0,t.jsxs)("button",{type:"button",className:"btn btn-primary shrink-0",disabled:!O||R,onClick:()=>void z(),children:[R?(0,t.jsx)(a.Loader2,{size:14,className:"animate-spin"}):null,"Add certificate"]})]})]})]})]})})}},67217,e=>{"use strict";e.s(["ImportDialog",()=>f,"openImport",()=>m]);var t=e.i(61666);e.i(24856);var s=e.i(90372),a=e.i(67938),n=e.i(27813),r=e.i(42709),l=e.i(87283),i=e.i(46443),o=e.i(83067),c=e.i(69578),d=e.i(56396),u=e.i(6278);let h="atc:import";function m(){window.dispatchEvent(new Event(h))}let p={postman:"Postman collection","postman-environment":"Postman environment",openapi:"OpenAPI",swagger:"Swagger 2.0"},x={GET:"text-ok",POST:"text-warn",PUT:"text-accent",PATCH:"text-accent",DELETE:"text-bad"};function f(){let[e,m]=(0,o.useState)(!1),[f,b]=(0,o.useState)(null),[g,v]=(0,o.useState)(""),[y,w]=(0,o.useState)(""),[j,k]=(0,o.useState)(null),[N,C]=(0,o.useState)(!1),[S,E]=(0,o.useState)(""),[T,A]=(0,o.useState)(!1),L=(0,o.useRef)(null),P=(0,o.useRef)(null),{refresh:I,index:R}=(0,u.useWorkspace)(),q=(0,d.useToast)(),$=(0,i.useRouter)(),M=(0,i.usePathname)();function D(e,t){k(null);try{let a=(0,s.importFile)(e,t);b(a),v(t),w(a.title.slice(0,60))}catch(e){b(null),k(e instanceof Error?e.message:"Could not read that file")}}async function z(e){if(e.size>0x1400000)return k(`${e.name} is larger than 20 MB`);D(await e.text(),e.name)}(0,o.useEffect)(()=>{let e=()=>{m(!0),b(null),k(null),C(!1),E("")};return window.addEventListener(h,e),()=>window.removeEventListener(h,e)},[]),(0,o.useEffect)(()=>{if(!e)return;P.current?.focus();let t=e=>"Escape"===e.key&&!T&&m(!1);return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e,T]);let H=(0,o.useMemo)(()=>{if(!f)return 0;let e=y.trim().toLowerCase();return(R?.requests??[]).filter(t=>t.collection.toLowerCase()===e).length},[R,f,y]);async function O(){if(f){A(!0);try{let e=y.trim()||f.title,t=t=>[e,...t.split("/").slice(1)].join("/"),s=await u.workspaceApi.importAll({requests:f.requests.map(e=>({collection:t(e.collection),name:e.name.slice(0,200),request:e.request})),folders:(f.folders??[]).map(e=>({path:t(e.path),settings:e.settings})),environments:f.environments});await I(),m(!1);let a=s.environments.added||s.environments.merged?` and ${s.environments.added+s.environments.merged} environment${s.environments.added+s.environments.merged===1?"":"s"}`:"";q(`Imported ${s.requests} request${1===s.requests?"":"s"}${a} — pick the environment next to the URL`,"success"),s.firstId&&(sessionStorage.setItem(c.OPEN_REQUEST_KEY,s.firstId),"/"===M?window.dispatchEvent(new Event(c.OPEN_REQUEST_EVENT)):$.push("/"))}catch(e){k(e instanceof Error?e.message:"Import failed")}finally{A(!1)}}}return e?(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-10",role:"presentation",onMouseDown:e=>e.target===e.currentTarget&&!T&&m(!1),children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true","aria-labelledby":"import-title",className:"w-full max-w-2xl rounded-xl border border-line bg-panel shadow-2xl",children:[(0,t.jsxs)("header",{className:"flex items-center gap-2 border-b border-line px-5 py-4",children:[(0,t.jsx)("h2",{id:"import-title",className:"text-base font-medium text-ink",children:"Import requests"}),(0,t.jsx)("button",{ref:P,type:"button",onClick:()=>m(!1),disabled:T,"aria-label":"Close",className:"ml-auto rounded p-1 text-mute hover:text-ink",children:(0,t.jsx)(l.X,{size:16})})]}),(0,t.jsxs)("div",{className:"space-y-4 px-5 py-4",children:[(0,t.jsxs)("p",{className:"text-sm text-mute",children:["From a ",(0,t.jsx)("span",{className:"text-ink",children:"Postman"})," collection or environment (v2.1 export), or an ",(0,t.jsx)("span",{className:"text-ink",children:"OpenAPI 3"})," / ",(0,t.jsx)("span",{className:"text-ink",children:"Swagger 2"})," file in JSON or YAML. Your current requests are not changed."]}),(0,t.jsx)("input",{ref:L,type:"file",accept:".json,.yaml,.yml,application/json,text/yaml",className:"sr-only","aria-label":"Choose a file to import",onChange:e=>{let t=e.target.files?.[0];e.target.value="",t&&z(t)}}),f||N?null:(0,t.jsxs)("button",{type:"button",onClick:()=>L.current?.click(),onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();let t=e.dataTransfer.files[0];t&&z(t)},className:"flex w-full flex-col items-center gap-1 rounded-lg border border-dashed border-line px-4 py-8 text-sm text-mute hover:border-accent hover:text-ink",children:[(0,t.jsx)(a.FileUp,{size:20,"aria-hidden":!0}),(0,t.jsx)("span",{className:"text-ink",children:"Choose a file"}),(0,t.jsx)("span",{className:"text-xs",children:"or drop it here · .json, .yaml, .yml"})]}),f?null:N?(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)("textarea",{value:S,onChange:e=>E(e.target.value),rows:8,placeholder:"Paste the JSON or YAML here","aria-label":"Paste a file's contents",className:"input w-full font-mono text-xs"}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)("button",{type:"button",className:"btn btn-primary py-1.5 text-xs",disabled:!S.trim(),onClick:()=>D(S,"pasted"),children:"Read it"}),(0,t.jsx)("button",{type:"button",className:"rounded-md px-2 py-1.5 text-xs text-mute hover:text-ink",onClick:()=>C(!1),children:"Back"})]})]}):(0,t.jsx)("button",{type:"button",className:"text-xs text-accent hover:underline",onClick:()=>C(!0),children:"Or paste it instead"}),f?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)("span",{className:"rounded-full border border-line px-2 py-0.5 text-xs text-mute",children:p[f.kind]}),(0,t.jsx)("span",{className:"font-medium text-ink",children:f.title}),(0,t.jsxs)("span",{className:"text-mute",children:["from ",g]}),(0,t.jsx)("button",{type:"button",className:"ml-auto text-xs text-accent hover:underline",onClick:()=>b(null),children:"Choose another file"})]}),f.requests.length?(0,t.jsxs)("label",{className:"flex flex-wrap items-center gap-2 text-sm",children:[(0,t.jsx)("span",{className:"text-mute",children:"Put the requests in collection"}),(0,t.jsx)("input",{value:y,onChange:e=>w(e.target.value.slice(0,60)),className:"input w-56 py-1","aria-label":"Collection name"}),H?(0,t.jsxs)("span",{className:"text-xs text-warn",children:[H," request",1===H?"":"s"," already in it — they are kept, new ones are added"]}):null]}):null,(0,t.jsxs)("ul",{className:"max-h-64 space-y-0.5 overflow-y-auto rounded-md border border-line p-2 text-sm",children:[f.requests.slice(0,300).map((e,s)=>(0,t.jsxs)("li",{className:"flex items-center gap-2 truncate",children:[(0,t.jsx)("span",{className:`w-14 shrink-0 font-mono text-xs ${x[e.request.method]??"text-mute"}`,children:e.request.method}),(0,t.jsxs)("span",{className:"truncate text-ink",children:[e.collection.includes("/")?(0,t.jsxs)("span",{className:"text-mute",children:[e.collection.split("/").slice(1).join(" › ")," › "]}):null,e.name]})]},s)),f.requests.length>300?(0,t.jsxs)("li",{className:"text-xs text-mute",children:["…and ",f.requests.length-300," more"]}):null,f.environments.map(e=>(0,t.jsxs)("li",{className:"flex items-center gap-2 truncate",children:[(0,t.jsx)("span",{className:"w-14 shrink-0 text-xs text-mute",children:"ENV"}),(0,t.jsx)("span",{className:"truncate text-ink",children:e.name}),(0,t.jsxs)("span",{className:"text-xs text-mute",children:["· ",e.variables.length," variable",1===e.variables.length?"":"s",e.variables.some(e=>e.secret)?", secrets encrypted":""]})]},e.name))]}),f.warnings.length?(0,t.jsxs)("div",{className:"rounded-md border border-warn/40 bg-warn/5 px-3 py-2 text-xs text-warn",children:[(0,t.jsxs)("p",{className:"mb-1 flex items-center gap-1.5 font-medium",children:[(0,t.jsx)(r.TriangleAlert,{size:13,"aria-hidden":!0})," ",f.warnings.length," thing",1===f.warnings.length?"":"s"," to know"]}),(0,t.jsxs)("ul",{className:"list-disc space-y-0.5 pl-5",children:[f.warnings.slice(0,12).map(e=>(0,t.jsx)("li",{children:e},e)),f.warnings.length>12?(0,t.jsxs)("li",{children:["…and ",f.warnings.length-12," more"]}):null]})]}):null]}):null,j?(0,t.jsx)("p",{role:"alert",className:"text-sm text-bad",children:j}):null]}),(0,t.jsxs)("footer",{className:"flex items-center justify-end gap-2 border-t border-line px-5 py-3",children:[(0,t.jsx)("button",{type:"button",className:"rounded-md px-3 py-1.5 text-sm text-mute hover:text-ink",disabled:T,onClick:()=>m(!1),children:"Cancel"}),(0,t.jsxs)("button",{type:"button",className:"btn btn-primary",disabled:!f||T||!f.requests.length&&!f.environments.length,onClick:()=>void O(),children:[T?(0,t.jsx)(n.Loader2,{size:16,className:"animate-spin"}):null,f?`Import ${[f.requests.length?`${f.requests.length} request${1===f.requests.length?"":"s"}`:"",f.environments.length?`${f.environments.length} environment${1===f.environments.length?"":"s"}`:""].filter(Boolean).join(" and ")}`:"Import"]})]})]})}):null}},6278,20054,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(78451),a=e.i(83067);let n={checked:!1,online:!1,k6Ready:!1,k6Label:"Checking engine…"},r=(0,a.createContext)(n);function l(){return(0,a.useContext)(r)}async function i(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error??`Engine error (${e.status})`);return t}e.s(["EngineHealthProvider",0,function({children:e}){let[s,l]=(0,a.useState)(n);return(0,a.useEffect)(()=>{let e=!1,t=async()=>{try{var t;let s,a=await fetch("/engine/health",{cache:"no-store"});if(!a.ok)throw Error(String(a.status));let n=await a.json();if(e)return;let r=!!n.k6?.available;l({checked:!0,online:"ok"===n.status,k6Ready:r,k6Label:r?(t=n.k6?.version,(s=t?.match(/v?\d+\.\d+\.\d+/))?`k6 ${s[0].startsWith("v")?s[0]:`v${s[0]}`}`:"k6 ready"):n.k6?.reason??"k6 not found",demoApi:n.demoApi,appVersion:n.version,dataDir:n.dataDir})}catch{e||l({checked:!0,online:!1,k6Ready:!1,k6Label:"Engine offline"})}};t();let s=window.setInterval(()=>void t(),8e3),a=()=>void t();return window.addEventListener("focus",a),()=>{e=!0,window.clearInterval(s),window.removeEventListener("focus",a)}},[]),(0,t.jsx)(r.Provider,{value:s,children:e})},"useEngineHealth",0,l],20054);let o=(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)}),c={index:()=>fetch("/engine/workspace",{cache:"no-store"}).then(e=>i(e)),get:e=>fetch(`/engine/workspace/requests/${encodeURIComponent(e)}`,{cache:"no-store"}).then(e=>i(e)),create:e=>o("POST","/engine/workspace/requests",e).then(e=>i(e)),update:(e,t)=>o("PUT",`/engine/workspace/requests/${encodeURIComponent(e)}`,t).then(e=>i(e)),remove:e=>o("DELETE",`/engine/workspace/requests/${encodeURIComponent(e)}`).then(e=>i(e)),importAll:e=>o("POST","/engine/workspace/import",e).then(e=>i(e)),saveEnvironments:e=>o("PUT","/engine/workspace/environments",e).then(e=>i(e))},d=(0,a.createContext)({index:null,refresh:async()=>{},environments:[],activeEnv:null,setActiveEnv:()=>{},vars:{},saveEnvironments:async()=>{},savedValues:{},rememberValues:()=>{},clearSavedValues:()=>{}}),u="apitestcenter-active-env",h="apitestcenter-saved-values";e.s(["WorkspaceProvider",0,function({children:e}){let[n,r]=(0,a.useState)(null),[i,o]=(0,a.useState)(null),[m,p]=(0,a.useState)({}),x=(0,a.useCallback)(async()=>{try{r(await c.index())}catch{}},[]);(0,a.useEffect)(()=>{try{o(localStorage.getItem(u))}catch{}try{let e=sessionStorage.getItem(h);e&&p(JSON.parse(e))}catch{}x();let e=()=>void x();return window.addEventListener("focus",e),()=>window.removeEventListener("focus",e)},[x]);let f=(0,a.useCallback)(e=>{o(e);try{e?localStorage.setItem(u,e):localStorage.removeItem(u)}catch{}},[]),b=(0,a.useCallback)(async e=>{await c.saveEnvironments(e),await x()},[x]),g=(0,a.useCallback)(e=>{p(e);try{Object.keys(e).length?sessionStorage.setItem(h,JSON.stringify(e)):sessionStorage.removeItem(h)}catch{}},[]),v=(0,a.useCallback)((e,t)=>{e.length&&p(s=>{let a={...s};for(let s of e)a[s.name]={value:s.value,from:t};try{sessionStorage.setItem(h,JSON.stringify(a))}catch{}return a})},[]),y=(0,a.useCallback)(()=>g({}),[g]),{demoApi:w}=l(),j=(0,a.useMemo)(()=>{let e=n?.environments??[],t=e.find(e=>e.id===i)??null,a=w?{practiceApi:w}:{},r=Object.fromEntries(Object.entries(m).map(([e,t])=>[e,t.value]));return{index:n,refresh:x,environments:e,activeEnv:t,setActiveEnv:f,vars:{...a,...(0,s.variablesOf)(t),...r},saveEnvironments:b,savedValues:m,rememberValues:v,clearSavedValues:y}},[n,i,x,f,b,w,m,v,y]);return(0,t.jsx)(d.Provider,{value:j,children:e})},"useWorkspace",0,function(){return(0,a.useContext)(d)},"workspaceApi",0,c],6278)},60961,e=>{"use strict";let t=(0,e.i(99522).default)("chevron-right",[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]);e.s(["ChevronRight",0,t],60961)},86856,e=>{"use strict";let t=(0,e.i(99522).default)("command",[["path",{d:"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3",key:"11bfej"}]]);e.s(["Command",0,t],86856)},80190,e=>{"use strict";let t=(0,e.i(99522).default)("external-link",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);e.s(["ExternalLink",0,t],80190)},20621,e=>{"use strict";let t=(0,e.i(99522).default)("folder-open",[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]]);e.s(["FolderOpen",0,t],20621)},19286,e=>{"use strict";let t=(0,e.i(99522).default)("key-round",[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]);e.s(["KeyRound",0,t],19286)},63966,e=>{"use strict";let t=(0,e.i(99522).default)("log-in",[["path",{d:"m10 17 5-5-5-5",key:"1bsop3"}],["path",{d:"M15 12H3",key:"6jk70r"}],["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4",key:"u53s6r"}]]);e.s(["LogIn",0,t],63966)},458,e=>{"use strict";let t=(0,e.i(99522).default)("refresh-cw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);e.s(["RefreshCw",0,t],458)},49913,e=>{"use strict";let t=(0,e.i(99522).default)("rotate-cw",[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]]);e.s(["RotateCw",0,t],49913)},88293,e=>{"use strict";let t=(0,e.i(99522).default)("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]);e.s(["Search",0,t],88293)},50962,e=>{"use strict";let t=(0,e.i(99522).default)("send",[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",key:"1ffxy3"}],["path",{d:"m21.854 2.147-10.94 10.939",key:"12cjpa"}]]);e.s(["Send",0,t],50962)},30135,e=>{"use strict";let t=(0,e.i(99522).default)("shield-check",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);e.s(["ShieldCheck",0,t],30135)},96659,e=>{"use strict";let t=(0,e.i(99522).default)("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);e.s(["Trash2",0,t],96659)},42709,e=>{"use strict";var t=e.i(30844);e.s(["TriangleAlert",()=>t.default])},48317,e=>{"use strict";var t=e.i(83067),s=(e,t,s,a,n,r,l,i)=>{let o=document.documentElement,c=["light","dark"];function d(t){var s;(Array.isArray(e)?e:[e]).forEach(e=>{let s="class"===e,a=s&&r?n.map(e=>r[e]||e):n;s?(o.classList.remove(...a),o.classList.add(r&&r[t]?r[t]:t)):o.setAttribute(e,t)}),s=t,i&&c.includes(s)&&(o.style.colorScheme=s)}if(a)d(a);else try{let e=localStorage.getItem(t)||s,a=l&&"system"===e?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;d(a)}catch(e){}},a=["light","dark"],n="(prefers-color-scheme: dark)",r="u"<typeof window,l=t.createContext(void 0),i={setTheme:e=>{},themes:[]},o=["light","dark"],c=({forcedTheme:e,disableTransitionOnChange:s=!1,enableSystem:r=!0,enableColorScheme:i=!0,storageKey:c="theme",themes:p=o,defaultTheme:x=r?"system":"light",attribute:f="data-theme",value:b,children:g,nonce:v,scriptProps:y})=>{let[w,j]=t.useState(()=>u(c,x)),[k,N]=t.useState(()=>"system"===w?m():w),C=b?Object.values(b):p,S=t.useCallback(e=>{let t=e;if(!t)return;"system"===e&&r&&(t=m());let n=b?b[t]:t,l=s?h(v):null,o=document.documentElement,c=e=>{"class"===e?(o.classList.remove(...C),n&&o.classList.add(n)):e.startsWith("data-")&&(n?o.setAttribute(e,n):o.removeAttribute(e))};if(Array.isArray(f)?f.forEach(c):c(f),i){let e=a.includes(x)?x:null,s=a.includes(t)?t:e;o.style.colorScheme=s}null==l||l()},[v]),E=t.useCallback(e=>{let t="function"==typeof e?e(w):e;j(t);try{localStorage.setItem(c,t)}catch(e){}},[w]),T=t.useCallback(t=>{N(m(t)),"system"===w&&r&&!e&&S("system")},[w,e]);t.useEffect(()=>{let e=window.matchMedia(n);return e.addListener(T),T(e),()=>e.removeListener(T)},[T]),t.useEffect(()=>{let e=e=>{e.key===c&&(e.newValue?j(e.newValue):E(x))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[E]),t.useEffect(()=>{S(null!=e?e:w)},[e,w]);let A=t.useMemo(()=>({theme:w,setTheme:E,forcedTheme:e,resolvedTheme:"system"===w?k:w,themes:r?[...p,"system"]:p,systemTheme:r?k:void 0}),[w,E,e,k,r,p]);return t.createElement(l.Provider,{value:A},t.createElement(d,{forcedTheme:e,storageKey:c,attribute:f,enableSystem:r,enableColorScheme:i,defaultTheme:x,value:b,themes:p,nonce:v,scriptProps:y}),g)},d=t.memo(({forcedTheme:e,storageKey:a,attribute:n,enableSystem:r,enableColorScheme:l,defaultTheme:i,value:o,themes:c,nonce:d,scriptProps:u})=>{let h=JSON.stringify([n,a,i,e,c,o,r,l]).slice(1,-1);return t.createElement("script",{...u,suppressHydrationWarning:!0,nonce:"u"<typeof window?d:"",dangerouslySetInnerHTML:{__html:`(${s.toString()})(${h})`}})}),u=(e,t)=>{let s;if(!r){try{s=localStorage.getItem(e)||void 0}catch(e){}return s||t}},h=e=>{let t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(t),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(t)},1)}},m=e=>(e||(e=window.matchMedia(n)),e.matches?"dark":"light");e.s(["ThemeProvider",0,e=>t.useContext(l)?t.createElement(t.Fragment,null,e.children):t.createElement(c,{...e}),"useTheme",0,()=>{var e;return null!=(e=t.useContext(l))?e:i}])},46443,(e,t,s)=>{t.exports=e.r(42512)}]);
@@ -0,0 +1,51 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,49186,e=>{"use strict";var t=e.i(61666);e.i(24856);var s=e.i(99522);let a=(0,s.default)("arrow-right",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]);var r=e.i(95486),n=e.i(27813);let l=(0,s.default)("pencil",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]);var i=e.i(3792),o=e.i(71189),d=e.i(50962);let c=(0,s.default)("send-horizontal",[["path",{d:"M3.714 3.048a.498.498 0 0 0-.683.627l2.843 7.627a2 2 0 0 1 0 1.396l-2.842 7.627a.498.498 0 0 0 .682.627l18-8.5a.5.5 0 0 0 0-.904z",key:"117uat"}],["path",{d:"M6 12h16",key:"s4cdu5"}]]);var p=e.i(66478),m=e.i(87283),u=e.i(50804),x=e.i(46443),h=e.i(83067),f=e.i(60617),b=e.i(88491),g=e.i(75117),y=e.i(62350),v=e.i(36558),w=e.i(17219);function j(e){return String(e).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("\n","&#10;")}let k=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
3
+ <fonts count="3">
4
+ <font><sz val="11"/><name val="Calibri"/></font>
5
+ <font><b/><sz val="11"/><color rgb="FFFFFFFF"/><name val="Calibri"/></font>
6
+ <font><sz val="10"/><color rgb="FF5C6778"/><name val="Calibri"/></font>
7
+ </fonts>
8
+ <fills count="6">
9
+ <fill><patternFill patternType="none"/></fill>
10
+ <fill><patternFill patternType="gray125"/></fill>
11
+ <fill><patternFill patternType="solid"><fgColor rgb="FF0B8F7C"/></patternFill></fill>
12
+ <fill><patternFill patternType="solid"><fgColor rgb="FFDCFCE7"/></patternFill></fill>
13
+ <fill><patternFill patternType="solid"><fgColor rgb="FFFEF3C7"/></patternFill></fill>
14
+ <fill><patternFill patternType="solid"><fgColor rgb="FFFECACA"/></patternFill></fill>
15
+ </fills>
16
+ <borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>
17
+ <cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>
18
+ <cellXfs count="6">
19
+ <xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>
20
+ <xf numFmtId="0" fontId="1" fillId="2" borderId="0" xfId="0" applyFont="1" applyFill="1" applyAlignment="1"><alignment horizontal="center" vertical="center"/></xf>
21
+ <xf numFmtId="0" fontId="2" fillId="0" borderId="0" xfId="0" applyFont="1" applyAlignment="1"><alignment wrapText="1" vertical="center"/></xf>
22
+ <xf numFmtId="0" fontId="0" fillId="3" borderId="0" xfId="0" applyFill="1"/>
23
+ <xf numFmtId="0" fontId="0" fillId="4" borderId="0" xfId="0" applyFill="1"/>
24
+ <xf numFmtId="0" fontId="0" fillId="5" borderId="0" xfId="0" applyFill="1"/>
25
+ </cellXfs>
26
+ </styleSheet>`;function N(){let e=new Date().toISOString().slice(0,19).replace(/[:T]/g,"-");return`compare-${e}.xlsx`}async function I(e,t,s){let a=e.map(e=>e.report),r=e.map(e=>e.title),n=a.length>=2?(0,f.compareKpis)(a):[],l=(0,f.overlayBuckets)(a),i=(0,b.compareVerdictRows)(e,s),o=[[{v:"Metric",s:1},...r.map(e=>({v:e,s:1})),{v:"Best",s:1}],...n.map(e=>[{v:e.label},...e.values.map((t,s)=>{var a;return{v:"ms"===(a=e.unit)?`${Math.round(t)} ms`:"rps"===a?`${t.toFixed(1)} rps`:"pct"===a?`${(100*t).toFixed(2)}%`:String(Math.round(t)),s:3*(e.winner===s)}}),{v:(0,b.compareWinnerLabel)(e,r)}]),[{v:"Run mode"},{v:t},...r.slice(1).map(()=>({v:""})),{v:""}]],d=[{v:"Seconds into test",s:1}];r.forEach(e=>{d.push({v:`${e} — 95th pct (ms)`,s:1}),d.push({v:`${e} — req/s`,s:1}),d.push({v:`${e} — error rate`,s:1}),d.push({v:`${e} — VUs`,s:1})});let c=[{name:"Side by side",rows:o},{name:"Over time",rows:[d,...l.map(e=>{let t=[{v:e.elapsedS}];return e.p95.forEach((s,a)=>{t.push({v:s??""}),t.push({v:e.rps[a]??""}),t.push({v:e.failedRate[a]??""}),t.push({v:e.vus[a]??""})}),t})]},{name:"Result summary",rows:[[{v:"API",s:1},{v:"Result",s:1},{v:"What this means",s:1}],...i.map(e=>{var t;return[{v:e.title},{v:e.overall,s:"pass"===(t=e.overall)?3:"warn"===t?4:5*("fail"===t)},{v:e.headline,s:2}]})]},...e.map((e,t)=>{var s;return{name:(s=e.title,(s.replace(/[\\/?*[\]:]/g,"").slice(0,24)||`API ${t+1}`).slice(0,31)),rows:[[{v:"Key",s:1},{v:"Value",s:1},{v:"What this means",s:1}],...(0,v.summaryExportRows)(e.report).map(e=>[{v:e.key},{v:e.value},{v:e.description,s:2}])]}})].map((e,t)=>{var s;let a,r,n;return{id:t+1,relId:`rId${t+1}`,name:e.name,xml:(s=e.rows,r=Array.from({length:a=s[0]?.length??0},(e,t)=>{let r=function(e,t,s=10,a=48){let r=s;for(let s of e){let e=s[t]?.v;void 0!==e&&(r=Math.max(r,String(e).length+2))}return Math.min(a,r)}(s,t,0===t?14:12,t===a-1&&a>=3?72:42);return`<col min="${t+1}" max="${t+1}" width="${r}" customWidth="1"/>`}).join(""),n=s.map((e,t)=>`<row r="${t+1}" ht="${0===t?22:18}" customHeight="1">${e.map((e,s)=>{var a;let r,n;return a=t+1,r=`${function(e){let t=e+1,s="";for(;t>0;)s=String.fromCharCode(65+(t-1)%26)+s,t=Math.floor((t-1)/26);return s}(s)}${a}`,n=void 0!==e.s?` s="${e.s}"`:"","number"==typeof e.v&&Number.isFinite(e.v)?`<c r="${r}"${n}><v>${e.v}</v></c>`:`<c r="${r}"${n} t="inlineStr"><is><t xml:space="preserve">${j(e.v)}</t></is></c>`}).join("")}</row>`).join(""),`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
27
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
28
+ <sheetViews><sheetView workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/></sheetView></sheetViews>
29
+ <cols>${r}</cols>
30
+ <sheetData>${n}</sheetData>
31
+ </worksheet>`)}}),p=c.map(e=>`<Override PartName="/xl/worksheets/sheet${e.id}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`).join("\n "),m=c.map(e=>`<sheet name="${j(e.name)}" sheetId="${e.id}" r:id="${e.relId}"/>`).join("\n "),u=c.map(e=>`<Relationship Id="${e.relId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet${e.id}.xml"/>`).join("\n "),x={"[Content_Types].xml":`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
32
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
33
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
34
+ <Default Extension="xml" ContentType="application/xml"/>
35
+ <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
36
+ <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
37
+ ${p}
38
+ </Types>`,"_rels/.rels":`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
39
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
40
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
41
+ </Relationships>`,"xl/workbook.xml":`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42
+ <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
43
+ <sheets>
44
+ ${m}
45
+ </sheets>
46
+ </workbook>`,"xl/_rels/workbook.xml.rels":`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
47
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
48
+ ${u}
49
+ <Relationship Id="rId${c.length+1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
50
+ </Relationships>`,"xl/styles.xml":k};for(let e of c)x[`xl/worksheets/sheet${e.id}.xml`]=e.xml;return new Blob([(0,w.zipStore)(x)],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})}async function S(e,t,s){let a=N().replace(/\.xlsx$/,""),r={[`${a}.xlsx`]:new Uint8Array(await (await I(e,t,s)).arrayBuffer()),[`${a}.json`]:(0,b.exportCompareJson)(e,t)};for(let t of e){if(!t.probe)continue;let e=t.title.replace(/[^\w.-]+/g,"-").slice(0,40)||t.id.slice(0,8);r[`${e}-probe.json`]=(0,b.exportProbeJson)(t.probe)}return{base:a,blob:(0,w.zipStore)(r)}}var C=e.i(15060),$=e.i(88153);function A({apis:e,mode:s,probes:a}){var n,l,i;let o,d,c,p,m,{slo:u}=(0,$.useSlo)(),x=N(),v=x.replace(/\.xlsx$/,""),j=Object.entries(a).filter(e=>!!e[1]),[k,F]=(0,h.useState)(!1),[R,E]=(0,h.useState)(null),[T,z]=(0,h.useState)(null);if(0===e.length)return null;let D=(n=e,l=s,i=u,o=n.map(e=>e.title),d=`Compare: ${o.join(" vs ")}`.slice(0,120),c=n.length>=2?(0,f.compareKpis)(n.map(e=>e.report)):[],p=[`APITestCenter compare (${l})`,"",...n.map(e=>`- ${e.title}: ${e.report.testName} [${e.report.status}]`),"",...c.map(e=>{let t=e.values.map((t,s)=>{var a,r;return`${o[s]}=${a=t,"ms"===(r=e.unit)?`${Math.round(a)}ms`:"rps"===r?`${a.toFixed(1)}/s`:"pct"===r?`${(100*a).toFixed(2)}%`:String(Math.round(a))}`}).join(", "),s=null==e.winner?"tie":o[e.winner]??"tie";return`${e.label}: ${t} (best: ${s})`})],i&&p.push("",`Performance targets: p95 ${i.p95Ms} ms, errors ${(100*i.errorRate).toFixed(1)}%`),p.push("","Attach the Excel or Zip export from APITestCenter."),{subject:d,body:m=p.join("\n"),mailto:`mailto:?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,gmail:`https://mail.google.com/mail/?view=cm&fs=1&tf=1&su=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`,outlook:`https://outlook.office.com/mail/deeplink/compose?subject=${encodeURIComponent(d)}&body=${encodeURIComponent(m)}`});async function O(){z(null),F(!1);try{let{base:t,blob:a}=await S(e,s,u),r={files:[new File([a],`${t}-export.zip`,{type:"application/zip"})],title:D.subject,text:D.body};if(navigator.canShare?.({files:r.files}))return void await navigator.share(r);E("mailto")}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;E("mailto"),z(e instanceof Error?e.message:"Share failed")}}return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsxs)("span",{className:"mr-1 flex items-center gap-1.5 text-xs text-mute",children:[(0,t.jsx)(g.Download,{size:14}),"Export"]}),(0,t.jsx)("button",{type:"button",disabled:e.length<2,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>void I(e,s,u).then(e=>(0,C.downloadBlob)(x,e)),children:"Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>(0,C.downloadText)(`${v}.json`,(0,b.exportCompareJson)(e,s),"application/json"),children:"JSON"}),(0,t.jsx)("button",{type:"button",disabled:0===j.length,className:"rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent disabled:opacity-40",onClick:()=>{let t={};for(let[s,a]of j){let r=e.find(e=>e.id===s),n=(r?.title??s).replace(/[^\w.-]+/g,"-").slice(0,40);t[`${n}-probe.json`]=(0,b.exportProbeJson)(a)}(0,C.downloadBlob)(`${v}-probes.zip`,(0,w.zipStore)(t))},children:"Response JSONs"}),(0,t.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",onClick:()=>void S(e,s,u).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:[(0,t.jsx)(g.Download,{size:12}),"Zip"]}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>F(e=>!e),className:"inline-flex items-center gap-1 rounded-md border border-line bg-panel-2 px-2.5 py-1 text-xs text-ink hover:border-accent hover:text-accent",children:[(0,t.jsx)(y.Share2,{size:12}),"Share",(0,t.jsx)(r.ChevronDown,{size:12})]}),k?(0,t.jsxs)("div",{className:"absolute right-0 z-20 mt-1 w-56 rounded-md border border-line bg-panel p-1 shadow-lg",children:[(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("gmail")},children:"Gmail"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("outlook")},children:"Outlook on the web"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>{F(!1),E("mailto")},children:"Default mail app"}),(0,t.jsx)("button",{type:"button",className:"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-ink hover:bg-panel-2",onClick:()=>void O(),children:"System share"})]}):null]})]}),T?(0,t.jsx)("p",{className:"max-w-md text-xs text-mute",children:T}):null,R?(0,t.jsx)(P,{apis:e,mode:s,target:R,links:D,onClose:()=>E(null)}):null]})}function P({apis:e,mode:s,target:a,links:r,onClose:n}){let{slo:l}=(0,$.useSlo)(),i={gmail:"Gmail",outlook:"Outlook on the web",mailto:"default mail app"},o="gmail"===a?r.gmail:"outlook"===a?r.outlook:r.mailto;return(0,t.jsx)("div",{className:"fixed inset-0 z-50 grid place-items-center bg-canvas/70 p-4",role:"presentation",onClick:n,children:(0,t.jsxs)("div",{role:"dialog","aria-modal":"true",className:"w-full max-w-md rounded-lg border border-line bg-panel p-4 shadow-xl",onClick:e=>e.stopPropagation(),children:[(0,t.jsxs)("h2",{className:"text-sm font-medium text-ink",children:["Share via ",i[a]]}),(0,t.jsx)("p",{className:"mt-2 text-xs leading-5 text-mute",children:"Download the compare package, then attach it in the compose window. Browsers cannot attach files for you."}),(0,t.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void I(e,s,l).then(e=>(0,C.downloadBlob)(N(),e)),children:"Download Excel"}),(0,t.jsx)("button",{type:"button",className:"rounded-md border border-line bg-panel-2 px-2.5 py-1.5 text-xs text-ink",onClick:()=>void S(e,s,l).then(({base:e,blob:t})=>(0,C.downloadBlob)(`${e}-export.zip`,t)),children:"Download Zip"}),(0,t.jsxs)("a",{href:o,target:"_blank",rel:"noreferrer",className:"rounded-md bg-accent px-2.5 py-1.5 text-xs font-medium text-canvas",onClick:n,children:["Open ",i[a]]}),(0,t.jsx)("button",{type:"button",className:"rounded-md px-2.5 py-1.5 text-xs text-mute",onClick:n,children:"Close"})]})]})})}var F=e.i(55658),R=e.i(53012),E=e.i(45404),T=e.i(29724),z=e.i(88231);function D({items:e,liveTabs:s,running:a,source:r,mode:l,slo:i,title:o,actions:d,status:c,exportBar:p}){let[m,u]=(0,h.useState)("all"),x=(0,h.useRef)(null),b=e.map((e,t)=>(0,f.compareSeriesLabel)(t,e.title)),g=a||!e.some(e=>e.tabId===m)?"all":m,y=e.filter(e=>!s.has(e.tabId)),v=!a&&y.length>=2?(0,F.compareFairness)(y.map(e=>e.report),y.map(t=>b[e.indexOf(t)])):null;return(0,t.jsxs)("div",{ref:x,className:"min-h-0 flex-1 overflow-y-auto",children:[(0,t.jsxs)("header",{className:"sticky top-0 z-10 border-b border-line bg-canvas/95 px-4 pt-3 backdrop-blur lg:px-6",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[(0,t.jsx)("h2",{className:"text-base font-medium text-ink",children:o}),(0,t.jsx)("div",{className:"ml-auto flex flex-wrap items-center gap-2",children:d})]}),(0,t.jsx)("div",{role:"tablist","aria-label":"Comparison or one run",className:"-mb-px mt-3 flex gap-1 overflow-x-auto",children:[{id:"all",label:"Comparison",color:null},...e.map((e,t)=>({id:e.tabId,label:b[t],color:(0,z.seriesColor)(t)}))].map(e=>{let r=g===e.id,l=s.has(e.id);return(0,t.jsxs)("button",{type:"button",role:"tab","aria-selected":r,disabled:a&&"all"!==e.id,title:a&&"all"!==e.id?"Each run's own report opens when the compare has finished":e.label,onClick:()=>{u(e.id),x.current?.scrollTo({top:0})},className:`flex max-w-[18rem] shrink-0 items-center gap-2 rounded-t-md border border-b-0 px-3 py-2 text-sm disabled:opacity-50 ${r?"border-line bg-panel font-medium text-ink":"border-transparent text-mute hover:bg-panel-2 hover:text-ink"}`,children:[e.color?(0,t.jsx)("span",{className:"h-2 w-2 shrink-0 rounded-full",style:{background:e.color},"aria-hidden":!0}):null,(0,t.jsx)("span",{className:"truncate",children:e.label}),l?(0,t.jsx)(n.Loader2,{size:12,className:"shrink-0 animate-spin text-accent","aria-label":"running"}):null]},e.id)})})]}),(0,t.jsx)("div",{className:"space-y-4 px-4 py-4 lg:px-6",children:"all"===g?(0,t.jsxs)(t.Fragment,{children:[c,p,v?.unfair?(0,t.jsxs)("p",{role:"note",className:"flex items-start gap-2 rounded-md border border-warn/40 bg-warn/10 px-3 py-2 text-sm text-ink",children:[(0,t.jsx)(R.AlertTriangle,{size:16,className:"mt-0.5 shrink-0 text-warn","aria-hidden":!0}),(0,t.jsxs)("span",{children:[v.unfair," Compare runs with the same load and length to say which API is faster."]})]}):null,(0,t.jsxs)("p",{className:"text-xs text-mute",children:["saved"===r?`Saved runs: ${e.map((e,t)=>{let s;return`${b[t]} ${Number.isNaN((s=new Date(e.report.startedAt)).getTime())?"":s.toLocaleString(void 0,{day:"numeric",month:"short",hour:"numeric",minute:"2-digit"})}`}).join(" · ")}.`:"parallel"===l?"Ran at the same time — the runs shared this computer's CPU and network, so treat the numbers as directional.":"Ran one after another with the same load.",v&&!v.unfair&&v.caveats.length?` Note: ${v.caveats.join("; ")}.`:""]}),e.length>=2?(0,t.jsx)(E.Dashboard,{scope:"compare",data:{reports:e.map(e=>e.report),titles:e.map((e,t)=>b[t]+(s.has(e.tabId)?" · live":"")),slo:i,live:a}}):(0,t.jsx)("p",{className:"rounded-lg border border-dashed border-line px-6 py-14 text-center text-sm text-mute",children:a?"The overlay appears when the first API is under way…":"The overlay needs at least two finished runs."})]}):(0,t.jsx)(T.ReportView,{report:e.find(e=>e.tabId===g).report,source:"engine"})})]})}var O=e.i(2385),q=e.i(19656);function L(e){let t=Math.max(0,Math.ceil(e/1e3)),s=Math.floor(t/60),a=t%60;return s>0?`${s}:${String(a).padStart(2,"0")}`:`${a}s`}function M(e){let t=Math.max(0,Math.round(e/1e3));if(t<60)return`${t}s`;let s=Math.floor(t/60),a=t%60;return a?`${s}m ${a}s`:`${s}m`}function U({mode:e,phase:s,liveRuns:a,startedAt:r,endedAt:n}){let[l,i]=(0,h.useState)(()=>Date.now()),o="running"===s||"probing"===s||"between"===s;return((0,h.useEffect)(()=>{if(!o)return;let e=setInterval(()=>i(Date.now()),250);return()=>clearInterval(e)},[o]),"idle"===s)?null:"probing"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Checking APIs"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Probing each API before load. This can take a few seconds."})]}):"between"===s?(0,t.jsxs)("div",{className:"rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-accent uppercase",children:"Preparing next API"}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:"Processing the last run and starting the next one. Sequence compares take a moment between APIs."}),r?(0,t.jsxs)("p",{className:"mt-1 font-mono text-sm text-ink",children:["Elapsed ",M(l-Date.parse(r))]}):null]}):"done"===s&&r&&n?(0,t.jsxs)("div",{className:"rounded-md border border-line bg-panel-2 px-3 py-2",children:[(0,t.jsx)("div",{className:"text-xs tracking-wide text-mute uppercase",children:"Overall time taken"}),(0,t.jsx)("p",{className:"mt-0.5 font-mono text-lg text-ink",children:(0,q.formatDuration)(r,n)}),(0,t.jsxs)("p",{className:"mt-0.5 text-xs text-mute",children:["Wall clock for the whole compare (",e,"), including probes and gaps between runs."]})]}):"running"!==s||0===a.length?null:(0,t.jsxs)("div",{className:"space-y-2",children:[a.map(e=>{let s=(0,O.expectedLoadMs)(e.report),a=Math.max(0,l-Date.parse(e.report.startedAt)),r=Math.max(0,s-a),n="running"===e.status&&0===r;return(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-md border border-accent/30 bg-accent-dim px-3 py-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"text-xs tracking-wide text-accent uppercase",children:["queued"===e.status?"Starting":n?"Finishing":"Load running"," · ",e.title]}),(0,t.jsx)("p",{className:"mt-0.5 text-xs text-mute",children:n?"Clock hit zero. k6 is letting in-flight requests finish.":`${L(a)} elapsed`})]}),(0,t.jsx)("div",{className:"font-mono text-2xl tabular text-ink",children:"queued"===e.status?"…":n?"—":L(r)})]},e.report.id)}),r?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Compare elapsed ",M(l-Date.parse(r))]}):null]})}var B=e.i(22543),J=e.i(63343),V=e.i(44794),H=e.i(31753),K=e.i(60566),_=e.i(39170),W=e.i(28867),X=e.i(56396);e.i(42674);var G=e.i(5305);let Z="apitestcenter-compare-draft";function Q(){return globalThis.crypto?.randomUUID?.()??`tab-${Date.now()}-${Math.random().toString(16).slice(2)}`}function Y(e){return{...(0,G.defaultRequestDraft)(),id:Q(),title:e}}function ee(){let e=Y("API 1");return{tabs:[e,Y("API 2")],activeId:e.id,load:{...G.DEFAULT_LOAD}}}function et(e,t){let s=e&&"object"==typeof e?e:{},a="string"==typeof s.title&&s.title.trim()||"string"==typeof s.label&&s.label.trim()||t;return{...(0,G.requestFromUnknown)(e),id:"string"==typeof s.id&&s.id?s.id:Q(),title:a,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)}]);
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,33622,e=>{"use strict";var t=e.i(61666);e.i(24856);var r=e.i(48191);function n(e){return!!e&&"object"==typeof e&&"string"==typeof e.id&&"string"==typeof e.testName&&Array.isArray(e.buckets)&&"object"==typeof e.summary&&null!==e.summary}var a=e.i(45404),s=e.i(29724),o=e.i(88153),l=e.i(56396),i=e.i(59180),c=e.i(67938),p=e.i(50804),d=e.i(83067);e.s(["default",0,function(){let[e,u]=(0,d.useState)(null),[x,f]=(0,d.useState)(null),[m,h]=(0,d.useState)(null),[y,b]=(0,d.useState)(null),[j,g]=(0,d.useState)(!1),[v,N]=(0,d.useState)(!1),[w,S]=(0,d.useState)(null),[O,k]=(0,d.useState)(!1),A=(0,l.useToast)(),{refresh:T}=(0,i.useHistory)();async function C(){k(!0);try{await i.historyApi.import(w),await T(),N(!0),A("Saved to History","success")}catch(e){A(e instanceof Error?e.message:"Could not save to History","error")}finally{k(!1)}}let U=(0,d.useCallback)(async e=>{h(null),N(!1),u(null),f(null);let t=e.name.toLowerCase();if(t.endsWith(".html")||t.endsWith(".xlsx")||t.endsWith(".csv")||t.endsWith(".zip")){b(e.name),h("Preview needs the JSON export from the lab. HTML and Excel are for sharing, not for opening back here.");return}try{let t=await e.text(),a=JSON.parse(t),s=function(e){if(!e||"object"!=typeof e)throw Error("That file is not JSON we can open.");if("compare"===e.kind||Array.isArray(e.apis)&&e.apis.length>0){if(!(e&&"object"==typeof e&&"compare"===e.kind&&Array.isArray(e.apis)&&e.apis.length>=1&&e.apis.every(e=>e&&"object"==typeof e&&n(e.report))))throw Error("Not a valid APITestCenter compare export.");return{kind:"compare",doc:{...e,apis:e.apis.map(e=>({...e,report:(0,r.repairSummary)(e.report)}))}}}if(n(e.report))return{kind:"report",report:(0,r.repairSummary)(e.report)};if(n(e))return{kind:"report",report:(0,r.repairSummary)(e)};throw Error("Not an APITestCenter report. Export JSON from the lab (not HTML or Excel).")}(a);S(a),b(e.name),"compare"===s.kind?f(s.doc):u(s.report)}catch(t){b(e.name),h(t instanceof Error?t.message:"Could not read that file.")}},[]);function E(e){e.preventDefault(),g(!0)}function D(e){e.preventDefault(),g(!1);let t=e.dataTransfer.files[0];t&&U(t)}let H=j?"border-accent bg-accent-dim":"border-line bg-panel",L=x?.apis.map(e=>e.title)??[],{slo:R}=(0,o.useSlo)();return(0,t.jsxs)("div",{className:"flex min-h-0 flex-1 flex-col p-6 lg:p-8",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h1",{className:"text-xl font-medium text-ink",children:"Open a report"}),(0,t.jsx)("p",{className:"mt-1 max-w-xl text-sm text-mute",children:"Reopen a JSON report you exported earlier — a single run or a compare. Excel and HTML exports are for sharing and can't be reopened."})]}),e||x?(0,t.jsxs)("label",{onDragOver:E,onDragLeave:()=>g(!1),onDrop:D,className:`inline-flex cursor-pointer items-center gap-2 rounded-md border border-dashed px-3 py-2 text-xs ${H}`,children:[(0,t.jsx)(c.FileUp,{size:14,className:"text-accent"}),"Replace JSON",(0,t.jsx)("input",{type:"file",accept:"application/json,.json",className:"sr-only",onChange:e=>{let t=e.target.files?.[0];t&&U(t),e.target.value=""}})]}):null]}),m?(0,t.jsx)("p",{className:"mt-4 text-sm text-bad",children:m}):null,x?(0,t.jsxs)("div",{className:"mt-6 space-y-4",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,t.jsxs)("p",{className:"text-xs text-mute",children:[y," · compare · ",x.mode]}),(0,t.jsx)("button",{type:"button",disabled:v||O,onClick:()=>void C(),className:"rounded-md border border-line px-3 py-1.5 text-xs text-ink hover:border-accent disabled:opacity-40",children:v?"Saved to History":"Keep in History"})]}),(0,t.jsx)(a.Dashboard,{scope:"compare",data:{reports:x.apis.map(e=>e.report),titles:L,slo:R,live:!1}}),(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Open"," ",(0,t.jsx)(p.default,{href:"/compare",className:"text-accent hover:underline",children:"Compare"})," ","to re-run these APIs live."]})]}):e?(0,t.jsxs)("div",{className:"mt-6 space-y-3",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,t.jsx)("p",{className:"text-xs text-mute",children:y}),(0,t.jsx)("button",{type:"button",disabled:v||O,onClick:()=>void C(),className:"rounded-md border border-line px-3 py-1.5 text-xs text-ink hover:border-accent disabled:opacity-40",children:v?"Saved to History":"Keep in History"})]}),v?(0,t.jsxs)("p",{className:"text-xs text-mute",children:["Open it anytime on"," ",(0,t.jsx)(p.default,{href:"/history",className:"text-accent hover:underline",children:"History"}),"."]}):null,(0,t.jsx)("div",{className:"rounded-lg border border-line bg-panel p-4",children:(0,t.jsx)(s.ReportView,{report:e,source:"file"})})]}):(0,t.jsxs)("label",{onDragOver:E,onDragLeave:()=>g(!1),onDrop:D,className:`mt-6 flex min-h-0 flex-1 cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed px-8 py-16 text-center ${H}`,children:[(0,t.jsx)(c.FileUp,{size:28,className:"text-accent"}),(0,t.jsx)("span",{className:"mt-4 text-base text-ink",children:"Drop a JSON report here, or click to choose"}),(0,t.jsx)("span",{className:"mt-2 max-w-md text-sm text-mute",children:"Single-run or compare JSON from Export. HTML, Excel, and zip are for sharing — they will not open here."}),(0,t.jsx)("span",{className:"mt-4 font-mono text-xs text-mute",children:"apitestcenter-*.json"}),(0,t.jsx)("input",{type:"file",accept:"application/json,.json",className:"sr-only",onChange:e=>{let t=e.target.files?.[0];t&&U(t),e.target.value=""}})]})]})}],33622)},17219,15060,e=>{"use strict";let t=new Uint32Array(256).map((e,t)=>{let r=t;for(let e=0;e<8;e++)r=1&r?0xedb88320^r>>>1:r>>>1;return r>>>0});function r(e){let t=new Uint8Array(2);return new DataView(t.buffer).setUint16(0,e,!0),t}function n(e){let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),t}function a(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),r=0;for(let n of e)t.set(n,r),r+=n.length;return t}function s(e,t){let r=URL.createObjectURL(t),n=document.createElement("a");n.href=r,n.download=e,document.body.appendChild(n),n.click(),n.remove(),URL.revokeObjectURL(r)}e.s(["zipStore",0,function(e){let s=new TextEncoder,o=[],l=[],i=0;for(let[c,p]of Object.entries(e)){let e=s.encode(c),d="string"==typeof p?s.encode(p):p,u=function(e){let r=0xffffffff;for(let n of e)r=t[(r^n)&255]^r>>>8;return(0xffffffff^r)>>>0}(d),x=a([n(0x4034b50),r(20),r(0),r(0),r(0),r(0),n(u),n(d.length),n(d.length),r(e.length),r(0),e,d]),f=a([n(0x2014b50),r(20),r(20),r(0),r(0),r(0),r(0),n(u),n(d.length),n(d.length),r(e.length),r(0),r(0),r(0),r(0),n(0),n(i),e]);o.push(x),l.push(f),i+=x.length}let c=a(l),p=a([n(0x6054b50),r(0),r(0),r(Object.keys(e).length),r(Object.keys(e).length),n(c.length),n(i),r(0)]),d=a([...o,c,p]);return new Blob([d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)],{type:"application/zip"})}],17219),e.s(["downloadBlob",0,s,"downloadText",0,function(e,t,r){s(e,new Blob([t],{type:r}))}],15060)}]);