@skrillex1224/playwright-toolkit 2.1.198 → 2.1.200
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 +152 -2
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +152 -2
- package/dist/index.js.map +2 -2
- package/dist/internals/proxy-meter.js +78 -0
- package/package.json +1 -1
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 = 500;
|
|
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,83 @@ 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
|
+
while (Date.now() < listenDeadline) {
|
|
773
|
+
const lifecycle = readState(statePath);
|
|
774
|
+
if (lifecycle?.status === "exited") {
|
|
775
|
+
return {
|
|
776
|
+
ok: false,
|
|
777
|
+
reason: "child_exit_before_ready",
|
|
778
|
+
childExitCode: lifecycle.exitCode,
|
|
779
|
+
latencyMs: Date.now() - startedAt
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
if (canConnectToPort(port)) {
|
|
783
|
+
firstConnectAt = Date.now();
|
|
784
|
+
break;
|
|
785
|
+
}
|
|
786
|
+
sleepSync(PROXY_METER_POLL_INTERVAL_MS);
|
|
787
|
+
}
|
|
788
|
+
if (!firstConnectAt) {
|
|
789
|
+
return {
|
|
790
|
+
ok: false,
|
|
791
|
+
reason: "listen_timeout",
|
|
792
|
+
childExitCode: readState(statePath)?.exitCode ?? null,
|
|
793
|
+
latencyMs: Date.now() - startedAt
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
const stableDeadline = firstConnectAt + PROXY_METER_STABLE_WINDOW_MS;
|
|
797
|
+
while (Date.now() < stableDeadline) {
|
|
798
|
+
const lifecycle = readState(statePath);
|
|
799
|
+
if (lifecycle?.status === "exited") {
|
|
800
|
+
return {
|
|
801
|
+
ok: false,
|
|
802
|
+
reason: "child_exit_before_ready",
|
|
803
|
+
childExitCode: lifecycle.exitCode,
|
|
804
|
+
latencyMs: Date.now() - startedAt
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
canConnectToPort(port);
|
|
808
|
+
sleepSync(PROXY_METER_POLL_INTERVAL_MS);
|
|
809
|
+
}
|
|
810
|
+
if (!canConnectToPort(port)) {
|
|
811
|
+
return {
|
|
812
|
+
ok: false,
|
|
813
|
+
reason: "stabilize_timeout",
|
|
814
|
+
childExitCode: readState(statePath)?.exitCode ?? null,
|
|
815
|
+
latencyMs: Date.now() - startedAt
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
return {
|
|
819
|
+
ok: true,
|
|
820
|
+
latencyMs: Date.now() - startedAt
|
|
821
|
+
};
|
|
822
|
+
};
|
|
713
823
|
var normalizeDomainRows = (hosts) => {
|
|
714
824
|
const rows = [];
|
|
715
825
|
let requestCount = 0;
|
|
@@ -858,15 +968,23 @@ var startProxyMeter = (options = {}) => {
|
|
|
858
968
|
const upstreamUrl = String(options.proxyUrl || "").trim();
|
|
859
969
|
if (!upstreamUrl) return null;
|
|
860
970
|
if (runtime && runtime.proc) {
|
|
971
|
+
const previousStatePath = runtime.statePath;
|
|
861
972
|
try {
|
|
862
973
|
runtime.proc.kill("SIGTERM");
|
|
863
974
|
} catch {
|
|
864
975
|
}
|
|
865
976
|
runtime = null;
|
|
977
|
+
if (previousStatePath) {
|
|
978
|
+
try {
|
|
979
|
+
(0, import_fs.rmSync)(previousStatePath, { force: true });
|
|
980
|
+
} catch {
|
|
981
|
+
}
|
|
982
|
+
}
|
|
866
983
|
}
|
|
867
984
|
observedDomainResourceTypes = /* @__PURE__ */ new Map();
|
|
868
985
|
const port = pickFreePort();
|
|
869
986
|
const logPath = ensureLogPath();
|
|
987
|
+
const statePath = ensureStatePath();
|
|
870
988
|
const scriptPath = resolveScriptPath();
|
|
871
989
|
const debugMode = Boolean(options.debugMode);
|
|
872
990
|
const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
|
|
@@ -877,7 +995,8 @@ var startProxyMeter = (options = {}) => {
|
|
|
877
995
|
PROXY_METER_UPSTREAM: upstreamUrl,
|
|
878
996
|
PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),
|
|
879
997
|
PROXY_METER_DEBUG: debugMode ? "1" : "0",
|
|
880
|
-
PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
|
|
998
|
+
PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents),
|
|
999
|
+
PROXY_METER_STATE: statePath
|
|
881
1000
|
};
|
|
882
1001
|
const child = (0, import_child_process.spawn)(process.execPath, [scriptPath], {
|
|
883
1002
|
env,
|
|
@@ -892,8 +1011,27 @@ var startProxyMeter = (options = {}) => {
|
|
|
892
1011
|
proc: child,
|
|
893
1012
|
port,
|
|
894
1013
|
logPath,
|
|
1014
|
+
statePath,
|
|
895
1015
|
startedAt: Date.now()
|
|
896
1016
|
};
|
|
1017
|
+
const readiness = waitForProxyMeterReady({ port, statePath });
|
|
1018
|
+
if (!readiness.ok) {
|
|
1019
|
+
logger2.warn(
|
|
1020
|
+
`[proxy-meter] startup failed reason=${readiness.reason} latency_ms=${readiness.latencyMs} exit_code=${readiness.childExitCode ?? "unknown"}`
|
|
1021
|
+
);
|
|
1022
|
+
try {
|
|
1023
|
+
child.kill("SIGTERM");
|
|
1024
|
+
} catch {
|
|
1025
|
+
}
|
|
1026
|
+
runtime = null;
|
|
1027
|
+
try {
|
|
1028
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1029
|
+
} catch {
|
|
1030
|
+
}
|
|
1031
|
+
throw new Error(`proxy-meter startup failed: ${readiness.reason}`);
|
|
1032
|
+
}
|
|
1033
|
+
runtime.startedAt = Date.now() - readiness.latencyMs;
|
|
1034
|
+
logger2.info(`[proxy-meter] ready latency_ms=${readiness.latencyMs} stable_window_ms=${PROXY_METER_STABLE_WINDOW_MS}`);
|
|
897
1035
|
registerCleanup();
|
|
898
1036
|
return { server: `http://127.0.0.1:${port}` };
|
|
899
1037
|
};
|
|
@@ -905,9 +1043,15 @@ var recordProxyMeterResourceType = (requestUrl, resourceType) => {
|
|
|
905
1043
|
};
|
|
906
1044
|
var stopProxyMeter = async () => {
|
|
907
1045
|
if (!runtime) return null;
|
|
908
|
-
const { proc, logPath } = runtime;
|
|
1046
|
+
const { proc, logPath, statePath } = runtime;
|
|
909
1047
|
if (!proc || proc.killed) {
|
|
910
1048
|
runtime = null;
|
|
1049
|
+
if (statePath) {
|
|
1050
|
+
try {
|
|
1051
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1052
|
+
} catch {
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
911
1055
|
return logPath || null;
|
|
912
1056
|
}
|
|
913
1057
|
await new Promise((resolve) => {
|
|
@@ -929,6 +1073,12 @@ var stopProxyMeter = async () => {
|
|
|
929
1073
|
}
|
|
930
1074
|
});
|
|
931
1075
|
runtime = null;
|
|
1076
|
+
if (statePath) {
|
|
1077
|
+
try {
|
|
1078
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1079
|
+
} catch {
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
932
1082
|
return logPath || null;
|
|
933
1083
|
};
|
|
934
1084
|
var getProxyMeterSnapshot = async (options = {}) => {
|