@testrelic/maestro-analytics 1.3.0-next.73 → 1.3.0-next.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -348,7 +348,7 @@ function generateRunDir(base) {
348
348
  }
349
349
  async function isMitmdumpAvailable() {
350
350
  return new Promise((resolvePromise) => {
351
- const child = (0, import_node_child_process.spawn)("mitmdump", ["--version"], { shell: true });
351
+ const child = (0, import_node_child_process.spawn)("mitmdump", ["--version"]);
352
352
  let resolved = false;
353
353
  const settle = (ok) => {
354
354
  if (resolved) return;
@@ -410,8 +410,7 @@ async function startNetworkProxy(options) {
410
410
  let child;
411
411
  try {
412
412
  child = (0, import_node_child_process.spawn)("mitmdump", args, {
413
- stdio: ["ignore", "pipe", "pipe"],
414
- shell: true
413
+ stdio: ["ignore", "pipe", "pipe"]
415
414
  });
416
415
  } catch (err) {
417
416
  if (verbose) {
@@ -475,7 +474,7 @@ var import_node_fs3 = require("fs");
475
474
  var NOOP_HANDLE = { teardown: async () => {
476
475
  } };
477
476
  function commandExists(cmd) {
478
- const result = (0, import_node_child_process2.spawnSync)(cmd, ["--version"], { shell: true, stdio: "ignore" });
477
+ const result = (0, import_node_child_process2.spawnSync)(cmd, ["--version"], { stdio: "ignore" });
479
478
  return result.error === void 0 || result.error.code !== "ENOENT";
480
479
  }
481
480
  function logHint(quiet, msg) {
@@ -507,7 +506,7 @@ function logManualInstructions(quiet, platform, proxyHost, proxyPort) {
507
506
  async function adb(args, deviceId) {
508
507
  return new Promise((resolvePromise) => {
509
508
  const full = deviceId ? ["-s", deviceId, ...args] : args;
510
- const child = (0, import_node_child_process2.spawn)("adb", full, { shell: true, stdio: ["ignore", "pipe", "pipe"] });
509
+ const child = (0, import_node_child_process2.spawn)("adb", full, { stdio: ["ignore", "pipe", "pipe"] });
511
510
  let out = "";
512
511
  let err = "";
513
512
  child.stdout?.on("data", (c) => {
@@ -547,7 +546,7 @@ async function setUpAndroidEmulator(opts) {
547
546
  }
548
547
  async function xcrun(args) {
549
548
  return new Promise((resolvePromise) => {
550
- const child = (0, import_node_child_process2.spawn)("xcrun", args, { shell: true, stdio: ["ignore", "pipe", "pipe"] });
549
+ const child = (0, import_node_child_process2.spawn)("xcrun", args, { stdio: ["ignore", "pipe", "pipe"] });
551
550
  let out = "";
552
551
  let err = "";
553
552
  child.stdout?.on("data", (c) => {
@@ -682,8 +681,7 @@ function runMaestroProc(args, junitPath, testOutputDir, debugOutputDir, networkJ
682
681
  const stdoutChunks = [];
683
682
  const stderrChunks = [];
684
683
  const proc = (0, import_node_child_process3.spawn)("maestro", args, {
685
- stdio: ["inherit", "pipe", "pipe"],
686
- shell: true
684
+ stdio: ["inherit", "pipe", "pipe"]
687
685
  });
688
686
  proc.stdout.on("data", (chunk) => {
689
687
  stdoutChunks.push(chunk);
@@ -3527,15 +3525,19 @@ function printConsoleSummary(summary, outputPath, htmlReportPath, quiet, aiDefec
3527
3525
  var import_node_child_process4 = require("child_process");
3528
3526
  function openInBrowser(filePath) {
3529
3527
  const platform = process.platform;
3530
- let command;
3528
+ let file;
3529
+ let args;
3531
3530
  if (platform === "darwin") {
3532
- command = `open "${filePath}"`;
3531
+ file = "open";
3532
+ args = [filePath];
3533
3533
  } else if (platform === "win32") {
3534
- command = `start "" "${filePath}"`;
3534
+ file = "cmd";
3535
+ args = ["/c", "start", "", filePath];
3535
3536
  } else {
3536
- command = `xdg-open "${filePath}"`;
3537
+ file = "xdg-open";
3538
+ args = [filePath];
3537
3539
  }
3538
- (0, import_node_child_process4.exec)(command, () => {
3540
+ (0, import_node_child_process4.execFile)(file, args, () => {
3539
3541
  });
3540
3542
  }
3541
3543
 
package/dist/index.cjs CHANGED
@@ -1231,9 +1231,9 @@ document.addEventListener('keydown',function(e){
1231
1231
  `}function qe(e,t,r,n,o){if(n||e.total===0)return;let s=`\u250C${"\u2500".repeat(62)}\u2510
1232
1232
  `,i=`\u2514${"\u2500".repeat(62)}\u2518
1233
1233
  `,a=O(""),l=s;l+=O("TestRelic AI - Maestro Test Report"),l+=a;let c=[];if(e.passed>0&&c.push(`${e.passed} \u2713`),e.failed>0&&c.push(`${e.failed} \u2717`),e.flaky>0&&c.push(`${e.flaky} \u26A0`),e.skipped>0&&c.push(`${e.skipped} skipped`),e.timedout>0&&c.push(`${e.timedout} timedout`),l+=O(`Flows: ${e.total} total (${c.join(" ")})`),e.totalAssertions>0&&(l+=O(`Assertions: ${e.totalAssertions} total (${e.passedAssertions} \u2713 ${e.failedAssertions} \u2717)`)),e.totalActionSteps>0){let d=[],u=e.actionStepsByCategory;u.ui_action&&d.push(`${u.ui_action} UI`),u.navigation&&d.push(`${u.navigation} nav`),u.custom_step&&d.push(`${u.custom_step} custom`);let p=d.length>0?` (${d.join(" ")})`:"";l+=O(`Steps: ${e.totalActionSteps} total${p}`);}if(o&&o.length>0){let d=o.filter(h=>h.severity==="critical").length,u=o.filter(h=>h.severity==="warning").length,p=o.filter(h=>h.severity==="info").length,y=[];d>0&&y.push(`${d} critical`),u>0&&y.push(`${u} warning`),p>0&&y.push(`${p} info`),l+=O(`AI Defects: ${o.length} found (${y.join(" ")})`);}l+=O(`Report: ${r}`),l+=O(`Data: ${t}`),l+=i,l+=`For more information visit us at https://docs.testrelic.ai
1234
- `,process.stderr.write(l);}function Ge(e){let t=process.platform,r;t==="darwin"?r=`open "${e}"`:t==="win32"?r=`start "" "${e}"`:r=`xdg-open "${e}"`,child_process.exec(r,()=>{});}function wo(){let e=[];try{let r=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));e.push(path.join(r,"proxy-addon","testrelic_capture.py")),e.push(path.join(r,"..","src","proxy-addon","testrelic_capture.py"));}catch{}let t=globalThis.__dirname;t&&e.push(path.join(t,"proxy-addon","testrelic_capture.py"));for(let r of e)if(fs.existsSync(r))return path.resolve(r);return null}function vo(e){if(e)return fs.mkdirSync(e,{recursive:true}),e;let t=crypto.randomBytes(6).toString("hex"),r=path.join(os$1.tmpdir(),`testrelic-maestro-network-${t}`);return fs.mkdirSync(r,{recursive:true}),r}async function ko(){return new Promise(e=>{let t=child_process.spawn("mitmdump",["--version"],{shell:true}),r=false,n=o=>{r||(r=true,e(o));};t.on("error",()=>n(false)),t.on("close",o=>n(o===0)),setTimeout(()=>{try{t.kill();}catch{}n(false);},5e3);})}async function Xt(e){let{config:t,verbose:r=true}=e;if(!t.enabled)return null;if(!await ko())return r&&process.stderr.write("\u26A0 TestRelic: --capture-network requested but `mitmdump` is not on PATH.\n Install mitmproxy (`brew install mitmproxy` / `pipx install mitmproxy`)\n or supply --har-path to import a HAR file instead.\n"),null;let n=wo();if(!n)return r&&process.stderr.write(`\u26A0 TestRelic: network-capture addon not found in package; skipping capture.
1235
- `),null;let o=vo(e.outputDir??t.outputDir??void 0),s=path.join(o,"network.jsonl"),i=["--listen-host",t.proxyHost,"--listen-port",String(t.proxyPort),"-s",n,"--set",`testrelic_output=${s}`,"--set",`testrelic_redact_headers=${t.redactHeaders.join(",")}`,"--set",`testrelic_redact_body_fields=${t.redactBodyFields.join(",")}`,"--set",`testrelic_max_body_bytes=${t.maxBodyBytes}`,"--set","console_eventlog_verbosity=warn","--set","termlog_verbosity=warn"],a;try{a=child_process.spawn("mitmdump",i,{stdio:["ignore","pipe","pipe"],shell:!0});}catch(c){return r&&process.stderr.write(`\u26A0 TestRelic: failed to spawn mitmdump: ${c.message}
1236
- `),null}a.stdout?.on("data",c=>{r&&process.stderr.write(`[mitmdump] ${c.toString("utf-8")}`);}),a.stderr?.on("data",c=>{r&&process.stderr.write(`[mitmdump] ${c.toString("utf-8")}`);}),await new Promise(c=>setTimeout(c,750));let l=()=>new Promise(c=>{if(a.killed||a.exitCode!==null){c();return}let d=false,u=()=>{d||(d=true,c());};a.once("close",u),a.once("exit",u);try{a.kill("SIGINT");}catch{try{a.kill();}catch{}}setTimeout(()=>{if(!d){try{a.kill("SIGKILL");}catch{}u();}},4e3);});return {outputPath:s,outputDir:o,host:t.proxyHost,port:t.proxyPort,stop:l}}var $={teardown:async()=>{}};function er(e){let t=child_process.spawnSync(e,["--version"],{shell:true,stdio:"ignore"});return t.error===void 0||t.error.code!=="ENOENT"}function E(e,t){e||process.stderr.write(`${t}
1234
+ `,process.stderr.write(l);}function Ge(e){let t=process.platform,r,n;t==="darwin"?(r="open",n=[e]):t==="win32"?(r="cmd",n=["/c","start","",e]):(r="xdg-open",n=[e]),child_process.execFile(r,n,()=>{});}function wo(){let e=[];try{let r=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));e.push(path.join(r,"proxy-addon","testrelic_capture.py")),e.push(path.join(r,"..","src","proxy-addon","testrelic_capture.py"));}catch{}let t=globalThis.__dirname;t&&e.push(path.join(t,"proxy-addon","testrelic_capture.py"));for(let r of e)if(fs.existsSync(r))return path.resolve(r);return null}function vo(e){if(e)return fs.mkdirSync(e,{recursive:true}),e;let t=crypto.randomBytes(6).toString("hex"),r=path.join(os$1.tmpdir(),`testrelic-maestro-network-${t}`);return fs.mkdirSync(r,{recursive:true}),r}async function ko(){return new Promise(e=>{let t=child_process.spawn("mitmdump",["--version"]),r=false,n=o=>{r||(r=true,e(o));};t.on("error",()=>n(false)),t.on("close",o=>n(o===0)),setTimeout(()=>{try{t.kill();}catch{}n(false);},5e3);})}async function Xt(e){let{config:t,verbose:r=true}=e;if(!t.enabled)return null;if(!await ko())return r&&process.stderr.write("\u26A0 TestRelic: --capture-network requested but `mitmdump` is not on PATH.\n Install mitmproxy (`brew install mitmproxy` / `pipx install mitmproxy`)\n or supply --har-path to import a HAR file instead.\n"),null;let n=wo();if(!n)return r&&process.stderr.write(`\u26A0 TestRelic: network-capture addon not found in package; skipping capture.
1235
+ `),null;let o=vo(e.outputDir??t.outputDir??void 0),s=path.join(o,"network.jsonl"),i=["--listen-host",t.proxyHost,"--listen-port",String(t.proxyPort),"-s",n,"--set",`testrelic_output=${s}`,"--set",`testrelic_redact_headers=${t.redactHeaders.join(",")}`,"--set",`testrelic_redact_body_fields=${t.redactBodyFields.join(",")}`,"--set",`testrelic_max_body_bytes=${t.maxBodyBytes}`,"--set","console_eventlog_verbosity=warn","--set","termlog_verbosity=warn"],a;try{a=child_process.spawn("mitmdump",i,{stdio:["ignore","pipe","pipe"]});}catch(c){return r&&process.stderr.write(`\u26A0 TestRelic: failed to spawn mitmdump: ${c.message}
1236
+ `),null}a.stdout?.on("data",c=>{r&&process.stderr.write(`[mitmdump] ${c.toString("utf-8")}`);}),a.stderr?.on("data",c=>{r&&process.stderr.write(`[mitmdump] ${c.toString("utf-8")}`);}),await new Promise(c=>setTimeout(c,750));let l=()=>new Promise(c=>{if(a.killed||a.exitCode!==null){c();return}let d=false,u=()=>{d||(d=true,c());};a.once("close",u),a.once("exit",u);try{a.kill("SIGINT");}catch{try{a.kill();}catch{}}setTimeout(()=>{if(!d){try{a.kill("SIGKILL");}catch{}u();}},4e3);});return {outputPath:s,outputDir:o,host:t.proxyHost,port:t.proxyPort,stop:l}}var $={teardown:async()=>{}};function er(e){let t=child_process.spawnSync(e,["--version"],{stdio:"ignore"});return t.error===void 0||t.error.code!=="ENOENT"}function E(e,t){e||process.stderr.write(`${t}
1237
1237
  `);}function U(e,t,r,n){e||(t==="android"?process.stderr.write(`\u2139 TestRelic: real-device Android capture \u2014 set the device proxy manually:
1238
1238
  Settings \u2192 Wi-Fi \u2192 (long-press your network) \u2192 Modify \u2192 Proxy: Manual
1239
1239
  Host: ${r} Port: ${n}
@@ -1244,14 +1244,14 @@ document.addEventListener('keydown',function(e){
1244
1244
  Then install + TRUST the mitmproxy CA:
1245
1245
  1. Open http://mitm.it from Safari on the device \u2192 install profile.
1246
1246
  2. Settings \u2192 General \u2192 About \u2192 Certificate Trust Settings \u2192 enable mitmproxy.
1247
- `));}async function Qt(e,t){return new Promise(r=>{let n=t?["-s",t,...e]:e,o=child_process.spawn("adb",n,{shell:true,stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout?.on("data",a=>{s+=a.toString();}),o.stderr?.on("data",a=>{i+=a.toString();}),o.on("error",()=>r({code:127,stdout:s,stderr:i||"adb not on PATH"})),o.on("close",a=>r({code:a??1,stdout:s,stderr:i}));})}async function To(e){let{deviceId:t,proxyHost:r,proxyPort:n,quiet:o,skipCertInstall:s}=e;if(!er("adb"))return E(o,"\u26A0 TestRelic: `adb` not on PATH; skipping automatic Android proxy setup. See manual instructions:"),U(o,"android",r,n),$;let i=await Qt(["shell","settings","put","global","http_proxy",`${r}:${n}`],t);return i.code!==0?(E(o,`\u26A0 TestRelic: adb set proxy failed: ${i.stderr.trim()||"unknown error"}`),U(o,"android",r,n),$):(E(o,`\u2139 TestRelic: Android proxy set to ${r}:${n} on ${t??"default device"}.`),s||E(o,`\u2139 TestRelic: if HTTPS calls fail, install the mitmproxy CA on the emulator:
1247
+ `));}async function Qt(e,t){return new Promise(r=>{let n=t?["-s",t,...e]:e,o=child_process.spawn("adb",n,{stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout?.on("data",a=>{s+=a.toString();}),o.stderr?.on("data",a=>{i+=a.toString();}),o.on("error",()=>r({code:127,stdout:s,stderr:i||"adb not on PATH"})),o.on("close",a=>r({code:a??1,stdout:s,stderr:i}));})}async function To(e){let{deviceId:t,proxyHost:r,proxyPort:n,quiet:o,skipCertInstall:s}=e;if(!er("adb"))return E(o,"\u26A0 TestRelic: `adb` not on PATH; skipping automatic Android proxy setup. See manual instructions:"),U(o,"android",r,n),$;let i=await Qt(["shell","settings","put","global","http_proxy",`${r}:${n}`],t);return i.code!==0?(E(o,`\u26A0 TestRelic: adb set proxy failed: ${i.stderr.trim()||"unknown error"}`),U(o,"android",r,n),$):(E(o,`\u2139 TestRelic: Android proxy set to ${r}:${n} on ${t??"default device"}.`),s||E(o,`\u2139 TestRelic: if HTTPS calls fail, install the mitmproxy CA on the emulator:
1248
1248
  open http://mitm.it from Chrome on the emulator and follow prompts,
1249
1249
  OR for a system-level install:
1250
1250
  adb root && adb remount && adb push <mitm-ca>.0 /system/etc/security/cacerts/ && adb reboot
1251
- Set --skip-cert-install to silence this hint.`),{teardown:async()=>{await Qt(["shell","settings","put","global","http_proxy",":0"],t);}})}async function Ao(e){return new Promise(t=>{let r=child_process.spawn("xcrun",e,{shell:true,stdio:["ignore","pipe","pipe"]}),n="",o="";r.stdout?.on("data",s=>{n+=s.toString();}),r.stderr?.on("data",s=>{o+=s.toString();}),r.on("error",()=>t({code:127,stdout:n,stderr:o||"xcrun not on PATH"})),r.on("close",s=>t({code:s??1,stdout:n,stderr:o}));})}async function Io(e){let{proxyHost:t,proxyPort:r,quiet:n,skipCertInstall:o}=e;if(process.platform!=="darwin")return E(n,"\u26A0 TestRelic: iOS simulator capture requires macOS; the host is not Darwin. Skipping setup."),U(n,"ios",t,r),$;if(!er("xcrun"))return E(n,"\u26A0 TestRelic: `xcrun` not on PATH; skipping automatic iOS simulator setup."),U(n,"ios",t,r),$;if(!o){let s=path.join(process.env.HOME??"",".mitmproxy","mitmproxy-ca-cert.pem");if(fs.existsSync(s)){let i=e.deviceId??"booted",a=await Ao(["simctl","keychain",i,"add-root-cert",s]);a.code===0?E(n,`\u2139 TestRelic: installed mitmproxy CA on iOS simulator (${i}).`):(E(n,`\u26A0 TestRelic: failed to add-root-cert via simctl: ${a.stderr.trim()}`),U(n,"ios",t,r));}else E(n,`\u26A0 TestRelic: mitmproxy CA not found at ${s}. Run mitmdump once to generate it,
1251
+ Set --skip-cert-install to silence this hint.`),{teardown:async()=>{await Qt(["shell","settings","put","global","http_proxy",":0"],t);}})}async function Ao(e){return new Promise(t=>{let r=child_process.spawn("xcrun",e,{stdio:["ignore","pipe","pipe"]}),n="",o="";r.stdout?.on("data",s=>{n+=s.toString();}),r.stderr?.on("data",s=>{o+=s.toString();}),r.on("error",()=>t({code:127,stdout:n,stderr:o||"xcrun not on PATH"})),r.on("close",s=>t({code:s??1,stdout:n,stderr:o}));})}async function Io(e){let{proxyHost:t,proxyPort:r,quiet:n,skipCertInstall:o}=e;if(process.platform!=="darwin")return E(n,"\u26A0 TestRelic: iOS simulator capture requires macOS; the host is not Darwin. Skipping setup."),U(n,"ios",t,r),$;if(!er("xcrun"))return E(n,"\u26A0 TestRelic: `xcrun` not on PATH; skipping automatic iOS simulator setup."),U(n,"ios",t,r),$;if(!o){let s=path.join(process.env.HOME??"",".mitmproxy","mitmproxy-ca-cert.pem");if(fs.existsSync(s)){let i=e.deviceId??"booted",a=await Ao(["simctl","keychain",i,"add-root-cert",s]);a.code===0?E(n,`\u2139 TestRelic: installed mitmproxy CA on iOS simulator (${i}).`):(E(n,`\u26A0 TestRelic: failed to add-root-cert via simctl: ${a.stderr.trim()}`),U(n,"ios",t,r));}else E(n,`\u26A0 TestRelic: mitmproxy CA not found at ${s}. Run mitmdump once to generate it,
1252
1252
  then re-run with --capture-network. Falling back to manual instructions:`),U(n,"ios",t,r);}return E(n,`\u2139 TestRelic: in the iOS simulator, configure Wi-Fi \u2192 (i) \u2192 Manual proxy:
1253
1253
  Server: ${t} Port: ${r}
1254
- (We do not set host-wide \`networksetup\` proxy automatically; see docs.)`),$}async function tr(e){switch(e.platform){case "android":return To(e);case "ios":return Io(e);case "web":return E(e.quiet,"\u2139 TestRelic: --capture-network ignored for Maestro web flows (browser already handles HTTP)."),$;default:return E(e.quiet,"\u26A0 TestRelic: target platform unknown; printing manual proxy setup instructions:"),U(e.quiet,"android",e.proxyHost,e.proxyPort),U(e.quiet,"ios",e.proxyHost,e.proxyPort),$}}function _o(){let e=crypto.randomBytes(8).toString("hex");return path.join(os$1.tmpdir(),`testrelic-maestro-${e}`)}function nr(e,t){let r=[];e.platform&&r.push("--platform",e.platform),e.device&&r.push("--device",e.device),r.push("test");let n=path.join(t,"report.xml"),o=path.join(t,"artifacts"),s=path.join(t,"debug");if(r.push("--format","junit"),r.push("--output",n),r.push("--test-output-dir",o),r.push("--debug-output",s),e.analyze&&r.push("--analyze"),e.includeTags&&r.push("--include-tags",e.includeTags),e.excludeTags&&r.push("--exclude-tags",e.excludeTags),e.shards&&e.shards>1&&r.push("--shards",String(e.shards)),e.config&&r.push("--config",e.config),e.env)for(let[i,a]of Object.entries(e.env))r.push("-e",`${i}=${a}`);return e.maestroArgs&&r.push(...e.maestroArgs),r.push(...e.flowPaths),r}function Lo(e){switch((e??"").toLowerCase()){case "android":return "android";case "ios":return "ios";case "web":return "web";default:return "unknown"}}function Do(e,t,r,n,o,s,i){return new Promise(a=>{let l=[],c=[],d=child_process.spawn("maestro",e,{stdio:["inherit","pipe","pipe"],shell:true});d.stdout.on("data",u=>{l.push(u),s||process.stdout.write(u);}),d.stderr.on("data",u=>{c.push(u),s||process.stderr.write(u);}),d.on("close",async u=>{try{await i();}catch{}a({exitCode:u??1,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:Buffer.concat(l).toString("utf-8"),stderr:Buffer.concat(c).toString("utf-8"),networkJsonlDir:o});}),d.on("error",async u=>{try{await i();}catch{}a({exitCode:127,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:"",stderr:`Failed to start maestro CLI: ${u.message}`,networkJsonlDir:o});});})}async function No(e,t={}){let r=e.outputDir?path.resolve(e.outputDir):_o();fs.mkdirSync(path.join(r,"artifacts"),{recursive:true}),fs.mkdirSync(path.join(r,"debug"),{recursive:true});let n=nr(e,r),o=path.join(r,"report.xml"),s=path.join(r,"artifacts"),i=path.join(r,"debug"),a=null,l=null,c=t.network;if(c?.enabled){let p=path.join(r,"network");a=await Xt({config:c,outputDir:p,verbose:!e.quiet}),a&&(l=await tr({platform:Lo(e.platform),deviceId:e.device,proxyHost:a.host,proxyPort:a.port,skipCertInstall:c.skipCertInstall,quiet:e.quiet}));}let d=a?.outputDir??null,u=async()=>{if(a&&await new Promise(p=>setTimeout(p,500)),l)try{await l.teardown();}catch{}if(a)try{await a.stop();}catch{}};return Do(n,o,s,i,d,e.quiet,u)}var ir="[REDACTED]";function or(e,t){if(!e)return null;let r=new Set(t.map(o=>o.toLowerCase())),n={};for(let[o,s]of Object.entries(e))n[o]=r.has(o.toLowerCase())?ir:s;return n}function Ve(e,t){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>Ve(n,t));let r={};for(let[n,o]of Object.entries(e))r[n]=t.has(n)?ir:Ve(o,t);return r}function sr(e,t){if(!e||t.length===0)return e;try{let r=JSON.parse(e),n=Ve(r,new Set(t));return JSON.stringify(n)}catch{return e}}function Je(e,t,r){return {...e,requestHeaders:or(e.requestHeaders,t),responseHeaders:or(e.responseHeaders,t),requestBody:sr(e.requestBody,r),responseBody:e.isBinary?e.responseBody:sr(e.responseBody,r)}}function We(e,t,r){let n=o=>typeof o=="string"?e.includes(o):o.test(e);return r.some(n)?false:t.length===0?true:t.some(n)}function Ho(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return typeof r.url!="string"||typeof r.method!="string"?null:{id:r.id??`api-call-${Date.now()}`,timestamp:r.timestamp??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:r.requestHeaders??null,requestBody:r.requestBody??null,responseStatusCode:r.responseStatusCode??null,responseStatusText:r.responseStatusText??null,responseHeaders:r.responseHeaders??null,responseBody:r.responseBody??null,responseTimeMs:typeof r.responseTimeMs=="number"?r.responseTimeMs:0,isBinary:r.isBinary??!1,error:r.error??null}}catch{return null}}function $o(e,t){let r=[];for(let n of e.split(/\r?\n/)){let o=Ho(n);o&&We(o.url,t.includeUrls,t.excludeUrls)&&r.push(Je(o,t.redactHeaders,t.redactBodyFields));}return r}function Bo(e,t){try{return $o(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function jo(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>t.endsWith(".jsonl")).map(t=>path.join(e,t))}catch{return []}}function ar(e){if(!e||e.length===0)return null;let t={};for(let r of e)typeof r.name=="string"&&typeof r.value=="string"&&(t[r.name]=r.value);return Object.keys(t).length>0?t:null}function zo(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.params)?e.params.map(t=>`${encodeURIComponent(t.name)}=${encodeURIComponent(t.value??"")}`).join("&"):null:null}function qo(e){return e?/^(image|audio|video|application\/(octet-stream|pdf|zip|protobuf))/.test(e):false}function Go(e,t){let r=e.request,n=e.response;if(!r?.method||!r.url)return null;let o=n?.content,s=qo(o?.mimeType);return {id:`har-call-${t}`,timestamp:e.startedDateTime??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:ar(r.headers),requestBody:zo(r.postData),responseStatusCode:typeof n?.status=="number"&&n.status>0?n.status:null,responseStatusText:n?.statusText??null,responseHeaders:ar(n?.headers),responseBody:o?.text??null,responseTimeMs:typeof e.time=="number"?e.time:0,isBinary:s,error:null}}function Vo(e,t){let r;try{r=JSON.parse(e);}catch{return []}let n=r.log?.entries??[],o=[];return n.forEach((s,i)=>{let a=Go(s,i);a&&We(a.url,t.includeUrls,t.excludeUrls)&&o.push(Je(a,t.redactHeaders,t.redactBodyFields));}),o}function Jo(e,t){try{return Vo(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function Wo(e,t){let r=new Map;for(let o of t)r.set(o.testId,[]);if(e.length===0||t.length===0)return r;let n=t.map(o=>({testId:o.testId,startMs:Date.parse(o.startedAt),endMs:Date.parse(o.completedAt)}));for(let o of e){let s=Date.parse(o.timestamp);if(!Number.isFinite(s))continue;let i=n.find(l=>Number.isFinite(l.startMs)&&Number.isFinite(l.endMs)&&s>=l.startMs&&s<=l.endMs);if(i){r.get(i.testId).push(o);continue}let a=null;for(let l of n){if(!Number.isFinite(l.startMs)||!Number.isFinite(l.endMs))continue;let c=s<l.startMs?l.startMs-s:s-l.endMs;(!a||c<a.dist)&&(a={testId:l.testId,dist:c});}a&&r.get(a.testId).push(o);}return r}function dr(e,t,r){if(!t.enabled&&!t.harPath)return new Map;let n=[];if(e)for(let o of jo(e))n.push(...Bo(o,t));return t.harPath&&fs.existsSync(t.harPath)&&n.push(...Jo(t.harPath,t)),n.length===0?new Map:Wo(n,r)}function ur(e){return e.map((t,r)=>({...t,id:`api-call-${r}`}))}var Xo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function Ke(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Xo.has(t.hostname)))throw core.createError(core.ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Qo=3e3;async function ee(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Qo);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function fr(e){return new Promise(t=>setTimeout(t,e))}async function pr(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string")return r.message}catch{}return `HTTP ${e.status}`}async function te(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(s.ok){let a=await s.json();return {accessToken:a.accessToken,refreshToken:a.refreshToken,expiresIn:a.expiresIn,orgId:a.orgId,orgName:a.orgName,userId:a.userId,userName:a.userName}}if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;if(!isNaN(l)&&l>0){await fr(l);let c=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(c.ok){let d=await c.json();return {accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn,orgId:d.orgId,orgName:d.orgName,userId:d.userId,userName:d.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return s.status===400?{code:"validation_error",message:await pr(s),statusCode:400}:s.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:s.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await pr(s),statusCode:s.status}}catch(s){return s instanceof DOMException&&s.name==="AbortError"?{code:"timeout",message:"Token exchange timed out.",statusCode:null}:{code:"network_error",message:"Failed to reach cloud for token exchange.",statusCode:null}}finally{clearTimeout(o);}}function re(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function Ye(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal});if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;!isNaN(l)&&l>0&&(await fr(l),s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal}));}if(!s.ok)return null;let i=await s.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn}}catch{return null}finally{clearTimeout(o);}}async function Xe(e,t,r,n,o,s){let i=new AbortController,a=setTimeout(()=>i.abort(),o);try{let l={gitId:r,displayName:n};s&&(l.branch=s);let c=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:i.signal});if(!c.ok)return null;let d=await c.json();return {repoId:d.repoId,displayName:d.displayName}}catch{return null}finally{clearTimeout(a);}}var ns=5e3;function H(e,t){try{return child_process.execSync(e,{cwd:t,timeout:ns,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function Qe(e){let t=H("git rev-parse --abbrev-ref HEAD",e),r=H("git rev-parse --short HEAD",e),n=H("git log -1 --pretty=%s",e),o=H("git log -1 --format=%an",e)??H("git config user.name",e),s=os(e),i=s?j(s):null;return {branch:t,commitSha:r,commitMessage:n,commitAuthor:o,remoteUrl:i}}function os(e){let t=H("git remote get-url origin",e);if(t)return t;let r=H("git remote",e);if(!r)return null;let n=r.split(`
1254
+ (We do not set host-wide \`networksetup\` proxy automatically; see docs.)`),$}async function tr(e){switch(e.platform){case "android":return To(e);case "ios":return Io(e);case "web":return E(e.quiet,"\u2139 TestRelic: --capture-network ignored for Maestro web flows (browser already handles HTTP)."),$;default:return E(e.quiet,"\u26A0 TestRelic: target platform unknown; printing manual proxy setup instructions:"),U(e.quiet,"android",e.proxyHost,e.proxyPort),U(e.quiet,"ios",e.proxyHost,e.proxyPort),$}}function _o(){let e=crypto.randomBytes(8).toString("hex");return path.join(os$1.tmpdir(),`testrelic-maestro-${e}`)}function nr(e,t){let r=[];e.platform&&r.push("--platform",e.platform),e.device&&r.push("--device",e.device),r.push("test");let n=path.join(t,"report.xml"),o=path.join(t,"artifacts"),s=path.join(t,"debug");if(r.push("--format","junit"),r.push("--output",n),r.push("--test-output-dir",o),r.push("--debug-output",s),e.analyze&&r.push("--analyze"),e.includeTags&&r.push("--include-tags",e.includeTags),e.excludeTags&&r.push("--exclude-tags",e.excludeTags),e.shards&&e.shards>1&&r.push("--shards",String(e.shards)),e.config&&r.push("--config",e.config),e.env)for(let[i,a]of Object.entries(e.env))r.push("-e",`${i}=${a}`);return e.maestroArgs&&r.push(...e.maestroArgs),r.push(...e.flowPaths),r}function Lo(e){switch((e??"").toLowerCase()){case "android":return "android";case "ios":return "ios";case "web":return "web";default:return "unknown"}}function Do(e,t,r,n,o,s,i){return new Promise(a=>{let l=[],c=[],d=child_process.spawn("maestro",e,{stdio:["inherit","pipe","pipe"]});d.stdout.on("data",u=>{l.push(u),s||process.stdout.write(u);}),d.stderr.on("data",u=>{c.push(u),s||process.stderr.write(u);}),d.on("close",async u=>{try{await i();}catch{}a({exitCode:u??1,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:Buffer.concat(l).toString("utf-8"),stderr:Buffer.concat(c).toString("utf-8"),networkJsonlDir:o});}),d.on("error",async u=>{try{await i();}catch{}a({exitCode:127,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:"",stderr:`Failed to start maestro CLI: ${u.message}`,networkJsonlDir:o});});})}async function No(e,t={}){let r=e.outputDir?path.resolve(e.outputDir):_o();fs.mkdirSync(path.join(r,"artifacts"),{recursive:true}),fs.mkdirSync(path.join(r,"debug"),{recursive:true});let n=nr(e,r),o=path.join(r,"report.xml"),s=path.join(r,"artifacts"),i=path.join(r,"debug"),a=null,l=null,c=t.network;if(c?.enabled){let p=path.join(r,"network");a=await Xt({config:c,outputDir:p,verbose:!e.quiet}),a&&(l=await tr({platform:Lo(e.platform),deviceId:e.device,proxyHost:a.host,proxyPort:a.port,skipCertInstall:c.skipCertInstall,quiet:e.quiet}));}let d=a?.outputDir??null,u=async()=>{if(a&&await new Promise(p=>setTimeout(p,500)),l)try{await l.teardown();}catch{}if(a)try{await a.stop();}catch{}};return Do(n,o,s,i,d,e.quiet,u)}var ir="[REDACTED]";function or(e,t){if(!e)return null;let r=new Set(t.map(o=>o.toLowerCase())),n={};for(let[o,s]of Object.entries(e))n[o]=r.has(o.toLowerCase())?ir:s;return n}function Ve(e,t){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>Ve(n,t));let r={};for(let[n,o]of Object.entries(e))r[n]=t.has(n)?ir:Ve(o,t);return r}function sr(e,t){if(!e||t.length===0)return e;try{let r=JSON.parse(e),n=Ve(r,new Set(t));return JSON.stringify(n)}catch{return e}}function Je(e,t,r){return {...e,requestHeaders:or(e.requestHeaders,t),responseHeaders:or(e.responseHeaders,t),requestBody:sr(e.requestBody,r),responseBody:e.isBinary?e.responseBody:sr(e.responseBody,r)}}function We(e,t,r){let n=o=>typeof o=="string"?e.includes(o):o.test(e);return r.some(n)?false:t.length===0?true:t.some(n)}function Ho(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return typeof r.url!="string"||typeof r.method!="string"?null:{id:r.id??`api-call-${Date.now()}`,timestamp:r.timestamp??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:r.requestHeaders??null,requestBody:r.requestBody??null,responseStatusCode:r.responseStatusCode??null,responseStatusText:r.responseStatusText??null,responseHeaders:r.responseHeaders??null,responseBody:r.responseBody??null,responseTimeMs:typeof r.responseTimeMs=="number"?r.responseTimeMs:0,isBinary:r.isBinary??!1,error:r.error??null}}catch{return null}}function $o(e,t){let r=[];for(let n of e.split(/\r?\n/)){let o=Ho(n);o&&We(o.url,t.includeUrls,t.excludeUrls)&&r.push(Je(o,t.redactHeaders,t.redactBodyFields));}return r}function Bo(e,t){try{return $o(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function jo(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>t.endsWith(".jsonl")).map(t=>path.join(e,t))}catch{return []}}function ar(e){if(!e||e.length===0)return null;let t={};for(let r of e)typeof r.name=="string"&&typeof r.value=="string"&&(t[r.name]=r.value);return Object.keys(t).length>0?t:null}function zo(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.params)?e.params.map(t=>`${encodeURIComponent(t.name)}=${encodeURIComponent(t.value??"")}`).join("&"):null:null}function qo(e){return e?/^(image|audio|video|application\/(octet-stream|pdf|zip|protobuf))/.test(e):false}function Go(e,t){let r=e.request,n=e.response;if(!r?.method||!r.url)return null;let o=n?.content,s=qo(o?.mimeType);return {id:`har-call-${t}`,timestamp:e.startedDateTime??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:ar(r.headers),requestBody:zo(r.postData),responseStatusCode:typeof n?.status=="number"&&n.status>0?n.status:null,responseStatusText:n?.statusText??null,responseHeaders:ar(n?.headers),responseBody:o?.text??null,responseTimeMs:typeof e.time=="number"?e.time:0,isBinary:s,error:null}}function Vo(e,t){let r;try{r=JSON.parse(e);}catch{return []}let n=r.log?.entries??[],o=[];return n.forEach((s,i)=>{let a=Go(s,i);a&&We(a.url,t.includeUrls,t.excludeUrls)&&o.push(Je(a,t.redactHeaders,t.redactBodyFields));}),o}function Jo(e,t){try{return Vo(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function Wo(e,t){let r=new Map;for(let o of t)r.set(o.testId,[]);if(e.length===0||t.length===0)return r;let n=t.map(o=>({testId:o.testId,startMs:Date.parse(o.startedAt),endMs:Date.parse(o.completedAt)}));for(let o of e){let s=Date.parse(o.timestamp);if(!Number.isFinite(s))continue;let i=n.find(l=>Number.isFinite(l.startMs)&&Number.isFinite(l.endMs)&&s>=l.startMs&&s<=l.endMs);if(i){r.get(i.testId).push(o);continue}let a=null;for(let l of n){if(!Number.isFinite(l.startMs)||!Number.isFinite(l.endMs))continue;let c=s<l.startMs?l.startMs-s:s-l.endMs;(!a||c<a.dist)&&(a={testId:l.testId,dist:c});}a&&r.get(a.testId).push(o);}return r}function dr(e,t,r){if(!t.enabled&&!t.harPath)return new Map;let n=[];if(e)for(let o of jo(e))n.push(...Bo(o,t));return t.harPath&&fs.existsSync(t.harPath)&&n.push(...Jo(t.harPath,t)),n.length===0?new Map:Wo(n,r)}function ur(e){return e.map((t,r)=>({...t,id:`api-call-${r}`}))}var Xo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function Ke(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Xo.has(t.hostname)))throw core.createError(core.ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Qo=3e3;async function ee(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Qo);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function fr(e){return new Promise(t=>setTimeout(t,e))}async function pr(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string")return r.message}catch{}return `HTTP ${e.status}`}async function te(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(s.ok){let a=await s.json();return {accessToken:a.accessToken,refreshToken:a.refreshToken,expiresIn:a.expiresIn,orgId:a.orgId,orgName:a.orgName,userId:a.userId,userName:a.userName}}if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;if(!isNaN(l)&&l>0){await fr(l);let c=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(c.ok){let d=await c.json();return {accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn,orgId:d.orgId,orgName:d.orgName,userId:d.userId,userName:d.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return s.status===400?{code:"validation_error",message:await pr(s),statusCode:400}:s.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:s.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await pr(s),statusCode:s.status}}catch(s){return s instanceof DOMException&&s.name==="AbortError"?{code:"timeout",message:"Token exchange timed out.",statusCode:null}:{code:"network_error",message:"Failed to reach cloud for token exchange.",statusCode:null}}finally{clearTimeout(o);}}function re(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function Ye(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal});if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;!isNaN(l)&&l>0&&(await fr(l),s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal}));}if(!s.ok)return null;let i=await s.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn}}catch{return null}finally{clearTimeout(o);}}async function Xe(e,t,r,n,o,s){let i=new AbortController,a=setTimeout(()=>i.abort(),o);try{let l={gitId:r,displayName:n};s&&(l.branch=s);let c=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:i.signal});if(!c.ok)return null;let d=await c.json();return {repoId:d.repoId,displayName:d.displayName}}catch{return null}finally{clearTimeout(a);}}var ns=5e3;function H(e,t){try{return child_process.execSync(e,{cwd:t,timeout:ns,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function Qe(e){let t=H("git rev-parse --abbrev-ref HEAD",e),r=H("git rev-parse --short HEAD",e),n=H("git log -1 --pretty=%s",e),o=H("git log -1 --format=%an",e)??H("git config user.name",e),s=os(e),i=s?j(s):null;return {branch:t,commitSha:r,commitMessage:n,commitAuthor:o,remoteUrl:i}}function os(e){let t=H("git remote get-url origin",e);if(t)return t;let r=H("git remote",e);if(!r)return null;let n=r.split(`
1255
1255
  `)[0]?.trim();return n?H(`git remote get-url ${n}`,e):null}function j(e){let t=e.trim();return t=t.replace(/^[a-z+]+:\/\//,""),t=t.replace(/^[^@]+@/,""),t=t.replace(/:(?!\d)/,"/"),t=t.replace(/\.git$/,""),t=t.replace(/\/+$/,""),t=t.replace(/^[^@/]+@/,""),t.toLowerCase()}function Ze(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function gr(e){try{let t=fs.readFileSync(path.join(e,"package.json"),"utf-8"),r=JSON.parse(t);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function z(e){let t=gr(e);return t||`local/${path.basename(e)}`}var ds="1.0.0",mr=10;function oe(e,t,r,n,o,s,i,a){try{fs.mkdirSync(e,{recursive:!0});let l=Date.now(),c=`${l}-${t}-${r}.json`,d=path.join(e,c),u={version:ds,queuedAt:new Date(l).toISOString(),reason:n,retryCount:0,targetEndpoint:o,method:s,payload:i,headers:a},p=d+".tmp";fs.writeFileSync(p,JSON.stringify(u,null,2),"utf-8"),fs.renameSync(p,d);}catch(l){l.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
1256
1256
  `):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
1257
1257
  `);}}async function tt(e,t,r){let n;try{n=fs.readdirSync(e).filter(s=>s.endsWith(".json")&&!s.endsWith(".tmp")).sort();}catch{return}if(n.length===0)return;let o=[];for(let s=0;s<n.length;s+=mr)o.push(n.slice(s,s+mr));for(let s of o)for(let i of s){let a=path.join(e,i);try{if(!fs.statSync(a).isFile())continue;let c=fs.readFileSync(a,"utf-8"),d=JSON.parse(c);if(!core.isValidQueueEntry(d)){fs.unlinkSync(a);continue}let u=d;if((await fetch(u.targetEndpoint,{method:u.method,headers:{...u.headers,Authorization:`Bearer ${r}`},body:JSON.stringify(u.payload)})).ok)fs.unlinkSync(a);else return}catch{return}}}function rt(e,t){try{let r=fs.readdirSync(e).filter(o=>o.endsWith(".json")&&!o.endsWith(".tmp")),n=Date.now();for(let o of r){let s=path.join(e,o);try{let i=fs.readFileSync(s,"utf-8"),l=JSON.parse(i).queuedAt;if(typeof l=="string"){let c=new Date(l).getTime();n-c>t&&fs.unlinkSync(s);}}catch{try{fs.unlinkSync(s);}catch{}}}}catch{}}var ys=3e5,bs=864e5,xs=6e4,br=3e4,xr="https://platform.testrelic.ai/settings/api-keys",J=class{constructor(t){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=t,this.authState={mode:"pending",accessToken:null,refreshToken:null,expiresAt:null,orgId:null,orgName:null,userId:null,userName:null};}async initialize(){if(!this.config||!this.config.apiKey){this.setLocalMode("no_api_key"),process.stderr.write(`\u2139 TestRelic: No API key configured. Running in local mode.