import * as NodeFSP from "node:fs/promises";import * as NodeNet from "node:net";import * as NodePath from "node:path";import * as NodeTimersPromises from "node:timers/promises"; const defaultTcpHosts = ["127.0.0.1", "localhost", "::1"]; async function fileExists(filePath) { try { await NodeFSP.access(filePath); return true; } catch { return false; }} function tcpPortIsReady({ host, port, connectTimeoutMs = 500 }) { return new Promise((resolveReady) => { const socket = NodeNet.createConnection({ host, port }); let settled = false; const finish = (ready) => { if (settled) { return; } settled = true; socket.removeAllListeners(); socket.destroy(); resolveReady(ready); }; socket.once("connect", () => { finish(true); }); socket.once("timeout", () => { finish(false); }); socket.once("error", () => { finish(false); }); socket.setTimeout(connectTimeoutMs); });} async function resolvePendingResources({ baseDir, files, tcpPort, tcpHosts, connectTimeoutMs }) { const pendingFiles = []; for (const relativeFilePath of files) { const ready = await fileExists(NodePath.resolve(baseDir, relativeFilePath)); if (!ready) { pendingFiles.push(relativeFilePath); } } let tcpReady = false; for (const host of tcpHosts) { tcpReady = await tcpPortIsReady({ host, port: tcpPort, connectTimeoutMs, }); if (tcpReady) { break; } } return { pendingFiles, tcpReady, };} export async function waitForResources({ baseDir, files = [], intervalMs = 100, timeoutMs = 120_000, tcpHost, tcpPort, connectTimeoutMs = 500,}) { if (!Number.isInteger(tcpPort) || tcpPort <= 0) { throw new TypeError("waitForResources requires a positive integer tcpPort"); } const startedAt = Date.now(); const tcpHosts = tcpHost ? [tcpHost] : defaultTcpHosts; while (true) { const { pendingFiles, tcpReady } = await resolvePendingResources({ baseDir, files, tcpPort, tcpHosts, connectTimeoutMs, }); if (pendingFiles.length === 0 && tcpReady) { return; } if (Date.now() - startedAt >= timeoutMs) { const pendingResources = []; if (!tcpReady) { pendingResources.push(tcpHost ? `tcp:${tcpHost}:${tcpPort}` : `tcp:${tcpPort}`); } for (const filePath of pendingFiles) { pendingResources.push(`file:${filePath}`); } throw new Error( `Timed out waiting for desktop dev resources after ${timeoutMs}ms: ${pendingResources.join(", ")}`, ); } await NodeTimersPromises.setTimeout(intervalMs); }}
import * as NodeFSP from "node:fs/promises";
import * as NodeNet from "node:net";
import * as NodePath from "node:path";
import * as NodeTimersPromises from "node:timers/promises";
const defaultTcpHosts = ["127.0.0.1", "localhost", "::1"];
async function fileExists(filePath) {
try {
await NodeFSP.access(filePath);
return true;
} catch {
return false;
}
}
function tcpPortIsReady({ host, port, connectTimeoutMs = 500 }) {
return new Promise((resolveReady) => {
const socket = NodeNet.createConnection({ host, port });
let settled = false;
const finish = (ready) => {
if (settled) {
return;
}
settled = true;
socket.removeAllListeners();
socket.destroy();
resolveReady(ready);
};
socket.once("connect", () => {
finish(true);
});
socket.once("timeout", () => {
finish(false);
});
socket.once("error", () => {
finish(false);
});
socket.setTimeout(connectTimeoutMs);
});
}
async function resolvePendingResources({ baseDir, files, tcpPort, tcpHosts, connectTimeoutMs }) {
const pendingFiles = [];
for (const relativeFilePath of files) {
const ready = await fileExists(NodePath.resolve(baseDir, relativeFilePath));
if (!ready) {
pendingFiles.push(relativeFilePath);
}
}
let tcpReady = false;
for (const host of tcpHosts) {
tcpReady = await tcpPortIsReady({
host,
port: tcpPort,
connectTimeoutMs,
});
if (tcpReady) {
break;
}
}
return {
pendingFiles,
tcpReady,
};
}
export async function waitForResources({
baseDir,
files = [],
intervalMs = 100,
timeoutMs = 120_000,
tcpHost,
tcpPort,
connectTimeoutMs = 500,
}) {
if (!Number.isInteger(tcpPort) || tcpPort <= 0) {
throw new TypeError("waitForResources requires a positive integer tcpPort");
}
const startedAt = Date.now();
const tcpHosts = tcpHost ? [tcpHost] : defaultTcpHosts;
while (true) {
const { pendingFiles, tcpReady } = await resolvePendingResources({
baseDir,
files,
tcpPort,
tcpHosts,
connectTimeoutMs,
});
if (pendingFiles.length === 0 && tcpReady) {
return;
}
if (Date.now() - startedAt >= timeoutMs) {
const pendingResources = [];
if (!tcpReady) {
pendingResources.push(tcpHost ? `tcp:${tcpHost}:${tcpPort}` : `tcp:${tcpPort}`);
}
for (const filePath of pendingFiles) {
pendingResources.push(`file:${filePath}`);
}
throw new Error(
`Timed out waiting for desktop dev resources after ${timeoutMs}ms: ${pendingResources.join(", ")}`,
);
}
await NodeTimersPromises.setTimeout(intervalMs);
}
}