@skrillex1224/playwright-toolkit 2.1.198 → 2.1.199

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/index.cjs CHANGED
@@ -599,9 +599,31 @@ var logger2 = createInternalLogger("ProxyMeter");
599
599
  var MAX_TOP_DOMAINS = 20;
600
600
  var FLUSH_INTERVAL_MS = 2e3;
601
601
  var DEFAULT_DEBUG_MAX_EVENTS = 400;
602
+ var PROXY_METER_READY_TIMEOUT_MS = 5e3;
603
+ var PROXY_METER_STABLE_WINDOW_MS = 2e3;
604
+ var PROXY_METER_POLL_INTERVAL_MS = 100;
605
+ var PROXY_METER_CONNECT_TIMEOUT_MS = 200;
602
606
  var runtime = null;
603
607
  var cleanupInstalled = false;
604
608
  var observedDomainResourceTypes = /* @__PURE__ */ new Map();
609
+ var sleepSignal = new Int32Array(new SharedArrayBuffer(4));
610
+ var portProbeScript = [
611
+ 'const net = require("net");',
612
+ "const port = Number(process.argv[1] || 0);",
613
+ "const timeout = Number(process.argv[2] || 200);",
614
+ "if (!Number.isFinite(port) || port <= 0) process.exit(2);",
615
+ 'const socket = net.connect({ host: "127.0.0.1", port });',
616
+ "let done = false;",
617
+ "const finish = (code) => {",
618
+ " if (done) return;",
619
+ " done = true;",
620
+ " try { socket.destroy(); } catch {}",
621
+ " process.exit(code);",
622
+ "};",
623
+ 'socket.once("connect", () => finish(0));',
624
+ 'socket.once("error", () => finish(1));',
625
+ "socket.setTimeout(timeout, () => finish(1));"
626
+ ].join("");
605
627
  var toSafeInt = (value) => {
606
628
  const num = Number(value);
607
629
  if (!Number.isFinite(num) || num <= 0) return 0;
@@ -700,6 +722,17 @@ var ensureLogPath = () => {
700
722
  const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;
701
723
  return import_path.default.join(baseDir, label);
702
724
  };
725
+ var ensureStatePath = () => {
726
+ const baseDir = resolveLogDir();
727
+ if (!(0, import_fs.existsSync)(baseDir)) {
728
+ try {
729
+ (0, import_fs.mkdirSync)(baseDir, { recursive: true });
730
+ } catch {
731
+ }
732
+ }
733
+ const suffix = `${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
734
+ return import_path.default.join(baseDir, `proxy-meter-state-${process.pid}-${suffix}.json`);
735
+ };
703
736
  var readSnapshot = (logPath) => {
704
737
  if (!logPath || !(0, import_fs.existsSync)(logPath)) return null;
705
738
  try {
@@ -710,6 +743,86 @@ var readSnapshot = (logPath) => {
710
743
  return null;
711
744
  }
712
745
  };
746
+ var readState = (statePath) => {
747
+ if (!statePath || !(0, import_fs.existsSync)(statePath)) return null;
748
+ try {
749
+ const raw = (0, import_fs.readFileSync)(statePath, "utf8");
750
+ if (!raw) return null;
751
+ return JSON.parse(raw);
752
+ } catch {
753
+ return null;
754
+ }
755
+ };
756
+ var sleepSync = (durationMs) => {
757
+ const timeout = Math.max(0, Number(durationMs) || 0);
758
+ if (timeout <= 0) return;
759
+ Atomics.wait(sleepSignal, 0, 0, timeout);
760
+ };
761
+ var canConnectToPort = (port, timeoutMs = PROXY_METER_CONNECT_TIMEOUT_MS) => {
762
+ const result = (0, import_child_process.spawnSync)(process.execPath, ["-e", portProbeScript, String(port), String(timeoutMs)], {
763
+ stdio: "ignore",
764
+ timeout: timeoutMs + 100
765
+ });
766
+ return result.status === 0;
767
+ };
768
+ var waitForProxyMeterReady = ({ port, statePath }) => {
769
+ const startedAt = Date.now();
770
+ const listenDeadline = startedAt + PROXY_METER_READY_TIMEOUT_MS;
771
+ let firstConnectAt = 0;
772
+ let stableHealthy = true;
773
+ while (Date.now() < listenDeadline) {
774
+ const lifecycle = readState(statePath);
775
+ if (lifecycle?.status === "exited") {
776
+ return {
777
+ ok: false,
778
+ reason: "child_exit_before_ready",
779
+ childExitCode: lifecycle.exitCode,
780
+ latencyMs: Date.now() - startedAt
781
+ };
782
+ }
783
+ if (canConnectToPort(port)) {
784
+ firstConnectAt = Date.now();
785
+ break;
786
+ }
787
+ sleepSync(PROXY_METER_POLL_INTERVAL_MS);
788
+ }
789
+ if (!firstConnectAt) {
790
+ return {
791
+ ok: false,
792
+ reason: "listen_timeout",
793
+ childExitCode: readState(statePath)?.exitCode ?? null,
794
+ latencyMs: Date.now() - startedAt
795
+ };
796
+ }
797
+ const stableDeadline = firstConnectAt + PROXY_METER_STABLE_WINDOW_MS;
798
+ while (Date.now() < stableDeadline) {
799
+ const lifecycle = readState(statePath);
800
+ if (lifecycle?.status === "exited") {
801
+ return {
802
+ ok: false,
803
+ reason: "stabilize_timeout",
804
+ childExitCode: lifecycle.exitCode,
805
+ latencyMs: Date.now() - startedAt
806
+ };
807
+ }
808
+ if (!canConnectToPort(port)) {
809
+ stableHealthy = false;
810
+ }
811
+ sleepSync(PROXY_METER_POLL_INTERVAL_MS);
812
+ }
813
+ if (!stableHealthy || !canConnectToPort(port)) {
814
+ return {
815
+ ok: false,
816
+ reason: "stabilize_timeout",
817
+ childExitCode: readState(statePath)?.exitCode ?? null,
818
+ latencyMs: Date.now() - startedAt
819
+ };
820
+ }
821
+ return {
822
+ ok: true,
823
+ latencyMs: Date.now() - startedAt
824
+ };
825
+ };
713
826
  var normalizeDomainRows = (hosts) => {
714
827
  const rows = [];
715
828
  let requestCount = 0;
@@ -858,15 +971,23 @@ var startProxyMeter = (options = {}) => {
858
971
  const upstreamUrl = String(options.proxyUrl || "").trim();
859
972
  if (!upstreamUrl) return null;
860
973
  if (runtime && runtime.proc) {
974
+ const previousStatePath = runtime.statePath;
861
975
  try {
862
976
  runtime.proc.kill("SIGTERM");
863
977
  } catch {
864
978
  }
865
979
  runtime = null;
980
+ if (previousStatePath) {
981
+ try {
982
+ (0, import_fs.rmSync)(previousStatePath, { force: true });
983
+ } catch {
984
+ }
985
+ }
866
986
  }
867
987
  observedDomainResourceTypes = /* @__PURE__ */ new Map();
868
988
  const port = pickFreePort();
869
989
  const logPath = ensureLogPath();
990
+ const statePath = ensureStatePath();
870
991
  const scriptPath = resolveScriptPath();
871
992
  const debugMode = Boolean(options.debugMode);
872
993
  const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
@@ -877,7 +998,8 @@ var startProxyMeter = (options = {}) => {
877
998
  PROXY_METER_UPSTREAM: upstreamUrl,
878
999
  PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),
879
1000
  PROXY_METER_DEBUG: debugMode ? "1" : "0",
880
- PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
1001
+ PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents),
1002
+ PROXY_METER_STATE: statePath
881
1003
  };
882
1004
  const child = (0, import_child_process.spawn)(process.execPath, [scriptPath], {
883
1005
  env,
@@ -892,8 +1014,27 @@ var startProxyMeter = (options = {}) => {
892
1014
  proc: child,
893
1015
  port,
894
1016
  logPath,
1017
+ statePath,
895
1018
  startedAt: Date.now()
896
1019
  };
1020
+ const readiness = waitForProxyMeterReady({ port, statePath });
1021
+ if (!readiness.ok) {
1022
+ logger2.warn(
1023
+ `[proxy-meter] startup failed reason=${readiness.reason} latency_ms=${readiness.latencyMs} exit_code=${readiness.childExitCode ?? "unknown"}`
1024
+ );
1025
+ try {
1026
+ child.kill("SIGTERM");
1027
+ } catch {
1028
+ }
1029
+ runtime = null;
1030
+ try {
1031
+ (0, import_fs.rmSync)(statePath, { force: true });
1032
+ } catch {
1033
+ }
1034
+ throw new Error(`proxy-meter startup failed: ${readiness.reason}`);
1035
+ }
1036
+ runtime.startedAt = Date.now() - readiness.latencyMs;
1037
+ logger2.info(`[proxy-meter] ready latency_ms=${readiness.latencyMs} stable_window_ms=${PROXY_METER_STABLE_WINDOW_MS}`);
897
1038
  registerCleanup();
898
1039
  return { server: `http://127.0.0.1:${port}` };
899
1040
  };
@@ -905,9 +1046,15 @@ var recordProxyMeterResourceType = (requestUrl, resourceType) => {
905
1046
  };
906
1047
  var stopProxyMeter = async () => {
907
1048
  if (!runtime) return null;
908
- const { proc, logPath } = runtime;
1049
+ const { proc, logPath, statePath } = runtime;
909
1050
  if (!proc || proc.killed) {
910
1051
  runtime = null;
1052
+ if (statePath) {
1053
+ try {
1054
+ (0, import_fs.rmSync)(statePath, { force: true });
1055
+ } catch {
1056
+ }
1057
+ }
911
1058
  return logPath || null;
912
1059
  }
913
1060
  await new Promise((resolve) => {
@@ -929,6 +1076,12 @@ var stopProxyMeter = async () => {
929
1076
  }
930
1077
  });
931
1078
  runtime = null;
1079
+ if (statePath) {
1080
+ try {
1081
+ (0, import_fs.rmSync)(statePath, { force: true });
1082
+ } catch {
1083
+ }
1084
+ }
932
1085
  return logPath || null;
933
1086
  };
934
1087
  var getProxyMeterSnapshot = async (options = {}) => {