everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
131 lines (129 loc) • 4.08 kB
JavaScript
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
let effect = require("effect");
let node_net = require("node:net");
//#region src/infra/preflight.ts
function parseLocalUrl(url) {
try {
const match = url.match(/:\/\/([^:/]+):(\d+)/);
if (!match) return null;
const host = match[1];
const port = Number.parseInt(match[2], 10);
if (Number.isNaN(port)) return null;
if (host !== "localhost" && host !== "127.0.0.1") return null;
return {
host,
port
};
} catch {
return null;
}
}
function checkTcpReachable(host, port, timeoutMs = 2e3) {
return effect.Effect.async((resume) => {
const socket = (0, node_net.createConnection)({
host,
port
});
const timer = setTimeout(() => {
socket.destroy();
resume(effect.Effect.succeed(false));
}, timeoutMs);
socket.once("connect", () => {
clearTimeout(timer);
socket.destroy();
resume(effect.Effect.succeed(true));
});
socket.once("error", () => {
clearTimeout(timer);
socket.destroy();
resume(effect.Effect.succeed(false));
});
});
}
function checkPgConnection(url) {
return effect.Effect.gen(function* () {
if (!(yield* checkTcpReachable(new URL(url).hostname, Number(new URL(url).port) || 5432, 4e3))) return false;
try {
const { Pool } = yield* effect.Effect.promise(() => Promise.resolve().then(() => require("../node_modules/pg/esm/index.cjs")));
const pool = new Pool({
connectionString: url,
connectionTimeoutMillis: 3e3
});
const client = yield* effect.Effect.promise(() => pool.connect().then((c) => ({
client: c,
pool
})));
try {
yield* effect.Effect.promise(() => client.client.query("SELECT 1"));
return true;
} finally {
client.client.release();
yield* effect.Effect.promise(() => client.pool.end().catch(() => {}));
}
} catch {
return false;
}
});
}
function preflightTargetsFromEnv(env) {
const targets = [];
for (const [secret, value] of Object.entries(env)) {
if (!value) continue;
if (secret.endsWith("_DATABASE_URL")) {
const parsed = parseLocalUrl(value);
if (parsed) targets.push({
secret,
host: parsed.host,
port: parsed.port,
kind: "postgres",
url: value
});
} else if (secret.endsWith("_REDIS_URL")) {
const parsed = parseLocalUrl(value);
if (parsed) targets.push({
secret,
host: parsed.host,
port: parsed.port,
kind: "redis",
url: value
});
}
}
return targets;
}
function preflightLocalInfra(env, overrides) {
const targets = preflightTargetsFromEnv(overrides ? {
...env,
...overrides
} : env);
if (targets.length === 0) return effect.Effect.succeed([]);
return effect.Effect.forEach(targets, (target) => effect.Effect.gen(function* () {
if (target.kind === "postgres") {
if (yield* checkPgConnection(target.url)) return null;
const tcpOk = yield* checkTcpReachable(target.host, target.port);
const pluginContext = target.secret.endsWith("_DATABASE_URL") ? ` The plugin for ${target.secret} runs inside the local host process, so this DB must be reachable. Run \`docker compose up -d --wait\` to start local Postgres/Redis.` : "";
if (tcpOk) return {
secret: target.secret,
host: target.host,
port: target.port,
error: `${target.secret} at ${target.host}:${target.port} is reachable but Postgres connection failed. Check credentials and database name.${pluginContext}`
};
return {
secret: target.secret,
host: target.host,
port: target.port,
error: `${target.secret} points to ${target.host}:${target.port} but nothing is listening.${pluginContext}`
};
}
if (yield* checkTcpReachable(target.host, target.port)) return null;
return {
secret: target.secret,
host: target.host,
port: target.port,
error: `${target.secret} points to ${target.host}:${target.port} but nothing is listening`
};
}), { concurrency: "unbounded" }).pipe(effect.Effect.map((results) => results.filter((r) => r !== null)));
}
//#endregion
exports.preflightLocalInfra = preflightLocalInfra;
//# sourceMappingURL=preflight.cjs.map